在Astyanax客户端中,NodeDiscoveryType与TOKEN_AWARE的含义是什么?

ars*_*nal 5 java cassandra astyanax

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

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
}
Run Code Online (Sandbox Code Playgroud)

假设我有24 cross colo cluster个节点,PHX中有colo/datacenter12个节点,SLC中有12 个节点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());
}
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释我之间有什么区别TOKEN_AWARENodeDiscoveryTypeVS TOKEN_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());
}
Run Code Online (Sandbox Code Playgroud)

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

    .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
    .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE)
Run Code Online (Sandbox Code Playgroud)

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

如果我错了,请纠正我?

Mat*_*elf 12

当谈到"节点发现"时,NodeDiscoveryType的TOKEN_AWARE与ConnectionPoolType的TOKEN_AWARE之间的关系是相互关联的,并且有些混乱.

NodeDiscoveryType 确定如下(并且它 - 通常不是通过setDiscoveryType()):

  • 如果您通过setSeeds提供Seeds且ConnectionPoolType为TOKEN_AWARE, NodeDiscoveryType为RING_DESCRIBE.
  • 如果您通过setSeeds提供种子,而ConnectionPoolType不是TOKEN_AWARE,那么将使用您配置的setDiscoveryType. 这是将使用您配置的NodeDiscoveryType(通过setDiscoveryType)的唯一情况.
  • 如果您未通过setSeeds提供Seeds且ConnectionPoolType为TOKEN_AWARE, NodeDiscoveryType为TOKEN_AWARE.
  • 如果您没有通过setSeeds提供种子,并且ConnectionPoolType不是TOKEN_AWARE,那么 NodeDiscoveryType是DISCOVERY_SERVICE.

节点发现

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

  • 如果 NodeDiscoveryType(从上面)是DISCOVERY_SERVICE,那么必须使用HostSupplier(via withHostSupplier).
  • 如果 NodeDiscoveryType(从上面)是RING_DESCRIBE,那么使用RingDescribeHostSupplier.
  • 如果 NodeDiscoveryType(从上面)是TOKEN_AWARE并且设置了HostSupplier(via withHostSupplier),那么使用带有RingDescribeHostSupplier的FilteringHostSupplier.
  • 如果 NodeDiscoveryType(从上面)是TOKEN_AWARE并且未设置HostSupplier,使用RingDescribeHostSupplier.

RingDescribe并使用本地DC

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

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

ConnectionPoolType

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

除非你提供HostSupplier,否则我会为Astyanax配置执行类似的操作.

.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()      
        .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
        .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE)
    )
Run Code Online (Sandbox Code Playgroud)

池优化

另一个考虑因素是在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% 
Run Code Online (Sandbox Code Playgroud)

请参阅Astyanax 配置

TLDR;

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