Что означает NodeDiscoveryType как TOKEN_AWARE в клиенте Astyanax?

Я нашел значение перечисления TOKEN_AWARE в клиенте Astyanax для Cassandra в com.netflix.astyanax.connectionpool.NodeDiscoveryType и пытаюсь понять, что он делает?

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.

И я подключаюсь к Cassandra с помощью клиента Astyanax следующим образом:

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_AWARE из NodeDiscoveryType и TOKEN_AWARE из ConnectionPoolType?

Спасибо за помощь.

Обновленный код

Ниже приведен код, который я использую до сих пор после внесения изменений:

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, поэтому нет смысла добавлять его снова. Я прав?

Поправьте меня, если я ошибаюсь?


person arsenal    schedule 09.05.2013    source источник
comment
techy я немного смущен. В одном посте вы задаете вопрос, а в следующем отвечаете на тот же вопрос.   -  person abhi    schedule 09.05.2013
comment
@abhi, я разместил другой вопрос, прежде чем узнал об этом. Но прежде чем публиковать что-либо, я пробую это сам, и с помощью TOKEN_AWARE NODE DISCOVERY я всегда получаю информацию обо всех узлах в центре обработки данных.   -  person arsenal    schedule 09.05.2013


Ответы (2)


Когда дело доходит до «обнаружения узла», отношения между TOKEN_AWARE для NodeDiscoveryType и TOKEN_AWARE для ConnectionPoolType взаимосвязаны и несколько сбивают с толку.

NodeDiscoveryType определен следующим образом (и обычно не через setDiscoveryType()):

  • Если вы предоставили Seeds через setSeeds и ConnectionPoolType имеет значение TOKEN_AWARE, то NodeDiscoveryType имеет значение RING_DESCRIBE.
  • Если вы предоставили Seeds через setSeeds, а ConnectionPoolType отличается от TOKEN_AWARE, то будет использоваться настроенный вами setDiscoveryType. Это единственный случай, когда будет использоваться настроенный вами NodeDiscoveryType (через setDiscoveryType).
  • Если вы не предоставили Seeds через setSeeds И ConnectionPoolType имеет значение TOKEN_AWARE, тогда NodeDiscoveryType имеет значение TOKEN_AWARE.
  • Если вы не предоставили Seeds через setSeeds И ConnectionPoolType не является TOKEN_AWARE тогда NodeDiscoveryType имеет значение DISCOVERY_SERVICE.

Обнаружение узла

Теперь, когда мы определили, как устанавливается NodeDiscoveryType, давайте посмотреть, как это влияет на фактическое обнаружение узлов. Обнаружение узла сводится к тому, какая реализация 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 разрешает подключения ко всем узлам в кольце, если вы не указали центр обработки данных. Итак, при настройке AstyanaxContext с помощью ConnectionPoolConfigurationImpl вы можете захотеть установитьLocalDatacenter с желаемым контроллером домена. Это гарантирует, что хосты из других контроллеров домена не находятся в пуле соединений и что ваши запросы являются локальными.

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

ConnectionPoolType

Вы также можете установить для ConnectionPoolType значение TOKEN_AWARE. Если это значение не установлено, по умолчанию оно будет равно ROUND_ROBIN (с использованием узлов из описанной выше работы по обнаружению узлов). TOKEN_AWARE ConnectionPoolType будет «отслеживать, какие узлы имеют какие токены, и пытаться разумно направлять трафик».

Я бы сделал что-то подобное для конфигурации Astyanax, если вы не предоставляете HostSupplier.

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

Оптимизация пула

Другим соображением может быть оптимизация использования пула с помощью Astyanax «осведомленность о задержке» в ConnectionPoolConfigurationImpl, но 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.

TLDR;

Таким образом, установите для NodeDiscoveryType значение RING_DESCRIBE (если вы не используете HostSupplier) и для ConnectionPoolType значение TOKEN_AWARE. Кроме того, используйте setLocalDatacenter, чтобы запросы оставались локальными для контроллера домена, и учитывайте параметры учета задержки.

person Matt Self    schedule 09.05.2013
comment
@TechGeeky сказал - Хорошо, круто. С моей текущей настройкой прямо сейчас для базы данных Cassandra в производстве у меня есть перекрестный кластер с 24 узлами, 12 узлами в SLC и 12 узлами в PHX. И коэффициент репликации равен 4, так что это означает, что в каждом цвете будет 2 копии одних и тех же данных. Теперь с текущей конфигурацией Astyanax, которую я использую в настоящее время, которая будет автоматически обнаруживать узлы только для каждого центра обработки данных, верно? В настоящее время это PHX. - Техгики - person Matt Self; 10.05.2013
comment
@TechGeeky сказал - продолжение вышеизложенного .... Предположим, я ищу rowKey 123, тогда он пойдет и получит данные из двух реплик в PHX colo, верно? Что тогда произойдет в этом случае, предположим, что два узла в PHX, которые будут содержать данные для rowKey 123, не работают? Затем он пойдет и получит данные от узлов реплик SLC colo? Я прав? - Техгики - person Matt Self; 10.05.2013
comment
Это мое понимание, но я этого не доказал. Я также изучаю/кодирую/разворачиваю этот материал, поэтому я отчитаюсь (поскольку моя установка будет очень похожей). Кроме того, я собираюсь удалить этот пост и переключить его обратно с вики сообщества... потому что я идиот (вероятно, это не гарантирует стиля вики). - person Matt Self; 10.05.2013
comment
Спасибо m4tty за предложение. Дайте мне знать, что вы обнаружите в случае использования, в котором данные, присутствующие в двух узлах, не работают. - person arsenal; 10.05.2013
comment
Следует отметить одну вещь: параметры задержки не должны устанавливаться в объекте конфигурации пула соединений с помощью методов .setLatencyAwareXX, поскольку Astyanax изменился. Вместо этого значения задержки передаются конструктору SmaLatencyScoreStrategyImpl (или любой другой используемой стратегии), и этот объект должен передаваться в .setLatencyScoreStrategy(). Я изменил код примера, чтобы отразить это. - person Matt Self; 12.05.2013
comment
Кажется, что параметр BadnessThreshold для 100%-й негодности должен быть равен 2, см. строка 183 файла AbstractLatencyScoreStrategyImpl - person Georg; 26.08.2013

С точки зрения реализации ConnectionPoolType.TOKEN_AWARE

Пул соединений, который разделяет соединения между хостами, которым принадлежит используемый токен. Когда токен недоступен или известно, что операция охватывает несколько токенов (например, пакетное изменение или индексный запрос), пулы узлов выбираются с использованием циклического перебора.

Где как NodeDiscoveryType.TOKEN_AWARE

Заново откройте информацию о кольце в сценарии с несколькими центрами обработки данных.

person abhi    schedule 09.05.2013