【问题标题】:What's the meaning of NodeDiscoveryType as TOKEN_AWARE in Astyanax client?在 Astyanax 客户端中 NodeDiscoveryType 作为 TOKEN_AWARE 是什么意思?
【发布时间】:2013-05-03 10:26:44
【问题描述】:

我在 com.netflix.astyanax.connectionpool.NodeDiscoveryType 的 Cassandra 的 Astyanax 客户端中找到了 TOKEN_AWARE 枚举值,并试图了解它的作用?

package com.netflix.astyanax.connectionpool;

public enum NodeDiscoveryType {
    /**
     * Discover nodes exclusively from doing a ring describe
     */
    RING_DESCRIBE,

    /**
     * Discover nodes exclusively from an external node discovery service
     */
    DISCOVERY_SERVICE,

    /**
     * Intersect ring describe and nodes from an external service. This solve
     * the multi-region ring describe problem where ring describe returns nodes
     * from other regions.
     */
    TOKEN_AWARE,

    /**
     * Use only nodes in the list of seeds
     */
    NONE
}

假设我有 24 个节点 cross colo cluster,其中 12 个节点在 PHX colo/datacenter 和 12 个节点在 SLC colo/datacenter。

我正在使用 Astyanax 客户端连接到 Cassandra,如下所示:

private CassandraAstyanaxConnection() {
    context = new AstyanaxContext.Builder()
                .forCluster(ModelConstants.CLUSTER)
                .forKeyspace(ModelConstants.KEYSPACE)
    .withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
        .setPort(9160)
        .setMaxConnsPerHost(40)
        .setSeeds("cdb03.vip.phx.host.com:9160,cdb04.vip.phx.host.com:9160")
    )
    .withAstyanaxConfiguration(new AstyanaxConfigurationImpl()      
        .setCqlVersion("3.0.0")
        .setTargetCassandraVersion("1.2")
        .setDiscoveryType(NodeDiscoveryType.TOKEN_AWARE))
    .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
    .buildKeyspace(ThriftFamilyFactory.getInstance());

    context.start();
    keyspace = context.getEntity();

    emp_cf = ColumnFamily.newColumnFamily(
        ModelConstants.COLUMN_FAMILY, 
        StringSerializer.get(), 
        StringSerializer.get());
}

谁能解释一下NodeDiscoveryType 的TOKEN_AWARE 和ConnectionPoolType 的TOKEN_AWARE 之间的区别是什么?

感谢您的帮助。

更新代码

以下是我进行更改后目前使用的代码-

private CassandraAstyanaxConnection() {

    context = new AstyanaxContext.Builder()
    .forCluster(ModelConstants.CLUSTER)
    .forKeyspace(ModelConstants.KEYSPACE)
    .withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
        .setPort(9160)
        .setMaxConnsPerHost(40)
        .setSeeds("cdb03.vip.phx.host.com:9160,cdb04.vip.phx.host.com:9160")
        .setLocalDatacenter("phx")
    )
    .withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
        .setCqlVersion("3.0.0")
        .setTargetCassandraVersion("1.2")
        .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE))
    .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
    .buildKeyspace(ThriftFamilyFactory.getInstance());

    context.start();
    keyspace = context.getEntity();

    emp_cf = ColumnFamily.newColumnFamily(
        ModelConstants.COLUMN_FAMILY, 
        StringSerializer.get(), 
        StringSerializer.get());
}

您在示例中提到您将使用-

    .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
    .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE)

这两个在一起对吗?但我相信TOKEN_AWARE ConnectionPoolType 默认使用RING_DESCRIBE,所以再次添加它没有意义。我说的对吗?

如果我错了,请纠正我?

【问题讨论】:

  • 技术我有点困惑。在一篇文章中,您提出了一个问题,而在下一篇文章中,您正在回答相同的问题。
  • @abhi,在我意识到这件事之前,我发布了其他问题。但在发布任何东西之前,我会自己尝试这些东西,并使用 TOKEN_AWARE NODE DISCOVERY 来获取整个数据中心的所有节点。

标签: java cassandra astyanax


【解决方案1】:

谈到“节点发现”时,NodeDiscoveryType 的 TOKEN_AWARE 和 ConnectionPoolType 的 TOKEN_AWARE 之间的关系是相互关联的,有些令人困惑。

NodeDiscoveryType 是 determined 如下(而且它通常不是通过 setDiscoveryType()):

  • 如果您通过 setSeeds 提供了 Seeds 并且 ConnectionPoolType 是 TOKEN_AWARE 那么 NodeDiscoveryType 是 RING_DESCRIBE。
  • 如果您通过 setSeeds 提供了 Seeds 并且 ConnectionPoolType 是 除了 TOKEN_AWARE then 您配置的 setDiscoveryType 之外的任何内容都将被使用。 这是唯一会使用您配置的 NodeDiscoveryType(通过 setDiscoveryType)的情况。
  • 如果您没有通过 setSeeds 提供种子并且 ConnectionPoolType 是 TOKEN_AWARE 则 NodeDiscoveryType 为 TOKEN_AWARE。
  • 如果您没有通过 setSeeds 提供种子并且 ConnectionPoolType 是 除了 TOKEN_AWARE then NodeDiscoveryType 之外的任何内容都是 DISCOVERY_SERVICE。

节点发现

现在我们已经确定了 NodeDiscoveryType 的设置方式,让我们来看看 see 它如何影响实际发现节点。节点发现归结为使用了 HostSupplier 的哪个实现(即Supplier<List<Host>>)。

  • 如果 NodeDiscoveryType(从上面)是 DISCOVERY_SERVICE 那么必须使用 HostSupplier(通过withHostSupplier)。
  • 如果 NodeDiscoveryType(从上面)是 RING_DESCRIBE 然后使用 RingDescribeHostSupplier。
  • 如果 NodeDiscoveryType(从上面)是 TOKEN_AWARE 并且 HostSupplier 已设置(通过withHostSupplier)那么将 FilteringHostSupplier 与 RingDescribeHostSupplier 一起使用。
  • 如果 NodeDiscoveryType(从上面)是 TOKEN_AWARE 并且没有设置 HostSupplier那么使用 RingDescribeHostSupplier。

RingDescribe 和使用本地 DC

根据您提供的配置,您最终会得到 RingDescribeHostSupplier。 RingDescribeHostSupplier 允许连接到环中的所有节点,除非您指定了数据中心。因此,在使用 ConnectionPoolConfigurationImpl 设置 AstyanaxContext 时,您可能希望使用所需的 DC 设置本地数据中心。这将确保来自其他 dc 的主机不在连接池中,并且您的请求是本地的。

.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
        .setPort(9160)
        .setMaxConnsPerHost(40)
        .setLocalDatacenter("phx")
        .setSeeds("cdb03.vip.phx.host.com:9160,cdb04.vip.phx.host.com:9160")
    )

连接池类型

您可能还想将 ConnectionPoolType 设置为 TOKEN_AWARE。当该值未设置时,它将默认为 ROUND_ROBIN(使用上述节点发现工作中的节点)。 TOKEN_AWARE Con​​nectionPoolType 将“跟踪哪些主机拥有哪些令牌并尝试智能地引导流量”。

除非您提供 HostSupplier,否则我会为 Astyanax 配置做类似的事情。

.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()      
        .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
        .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE)
    )

池优化

另一个考虑因素是在 ConnectionPoolConfigurationImpl 上使用 Astyanax“延迟感知”优化池使用,但在设置上使用 YMMV。例如:

.setLatencyScoreStrategy(new SmaLatencyScoreStrategyImpl(10000,10000,100,0.50))
// The constructor takes:
//  UpdateInterval: 10000 : Will resort hosts per token partition every 10 seconds
//  ResetInterval: 10000 : Will clear the latency every 10 seconds
//  WindowSize: 100 : Uses last 100 latency samples
//  BadnessThreshold: 0.50 : Will sort hosts if a host is more than 100% 

见 Astyanax Configuration

TLDR;

总之,将 NodeDiscoveryType 设置为 RING_DESCRIBE(如果您不使用 HostSupplier)并将 ConnectionPoolType 设置为 TOKEN_AWARE。此外,使用 setLocalDatacenter 将请求保持在 dc 本地,并考虑延迟感知设置。

【讨论】:

  • @TechGeeky 说- 好酷。使用我目前在生产中为 Cassandra 数据库设置的当前设置,我有 24 个节点、SLC 中的 12 个节点和 PHX 中的 12 个节点的跨 colo 集群。复制因子为 4,这意味着每个 colo 中将有 2 个相同数据的副本。现在使用我当前使用的 Astyanax 的当前配置,它只会自动发现每个数据中心的节点,对吗?目前是PHX。 – TechGeeky
  • @TechGeeky 说-从上面继续......假设我正在寻找 rowKey 123 那么它将去从 PHX colo 的两个副本中获取数据,对吗?那么在这种情况下会发生什么,假设 PHX 中包含 rowKey 123 数据的两个节点已关闭?然后它会去从 SLC colo replicas 节点获取数据?我对么? – TechGeeky
  • 这是我的理解,但我没有证明。我也在学习/编码/部署这些东西,所以我会报告(因为我的设置将非常相似)。另外,我要删除这篇文章并将其从社区 wiki 切换回来......因为我是个白痴(它可能不保证是 wiki 风格)。
  • 感谢 m4tty 的建议。让我知道您对两个节点中存在的数据已关闭的用例有何发现。
  • 需要注意的一点:不应通过 .setLatencyAwareXX 方法在连接池配置对象上设置“延迟”设置,因为 Astyanax 已更改。而是将延迟值提供给 SmaLatencyScoreStrategyImpl 的构造函数(或使用的任何策略),并且该对象应提供给 .setLatencyScoreStrategy()。我已更改示例代码以反映这一点。
【解决方案2】:

明智的实施ConnectionPoolType.TOKEN_AWARE

连接池,由拥有正在操作的令牌的主机划分连接。当令牌不可用或已知操作跨越多个令牌(例如批量变异或索引查询)时,将使用循环法挑选主机池。

在哪里NodeDiscoveryType.TOKEN_AWARE

在多数据中心场景中重新发现环描述信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-19
    • 2013-05-27
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 2018-05-10
    相关资源
    最近更新 更多