我在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,其中PHX colo/datacenter中有12个节点,而SLC colo/datacenter中有12个节点。

我正在使用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());
}

谁能解释我TOKEN_AWARENodeDiscoveryTypeTOKEN_AWAREConnectionPoolType之间的区别是什么?

谢谢您的帮助。

更新代码

以下是我到目前为止所做的更改后使用的代码-
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,因此再次添加它没有任何意义。我对吗?

如果我错了纠正我吗?

最佳答案

对于“节点发现”,NodeDiscoveryType的TOKEN_AWARE和ConnectionPoolType的TOKEN_AWARE之间的关系是相互关联的,并且有些混乱。

NodeDiscoveryType是determined,如下所示(并且-通常-不是通过setDiscoveryType()进行的):

  • 如果是,则您通过setSeeds和ConnectionPoolType提供了Seeds
    TOKEN_AWARE ,然后 NodeDiscoveryType为RING_DESCRIBE。
  • 如果是,则您通过setSeeds和ConnectionPoolType提供了Seeds
    除了TOKEN_AWARE 以外,其他任何东西都将使用您配置的setDiscoveryType。这是唯一使用配置的NodeDiscoveryType(通过setDiscoveryType)的情况。
  • 如果您未通过setSeeds提供种子,则ConnectionPoolType为
    TOKEN_AWARE ,则 NodeDiscoveryType为TOKEN_AWARE。
  • 如果您未通过setSeeds提供种子,则ConnectionPoolType为
    除了TOKEN_AWARE 以外的其他任何东西,然后 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设置LocalDatacenter。这样可以确保来自其他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本地,并考虑延迟感知设置。

    07-24 21:59