NoHostAvailableException 和 NoNodeAvailableException 疑难解答

NoHostAvailableException 是一个顶级包装器异常,有许多可能的原因和内部异常,其中许多可能与客户端相关。 如果群集或连接设置存在一些问题,或者一个或多个 Cassandra 节点不可用,则往往会发生此异常。

本文探讨了此异常的可能原因,并讨论了有关所使用的客户端驱动程序的具体详细信息。

驱动程序设置

NoHostAvailableException 最常见的一个原因是默认驱动程序设置。 建议使用本文末尾列出的设置。 以下是一些说明性信息:

  • 每个主机的连接数的默认值为 1,不建议将其用于 Azure Cosmos DB。 建议的最小值为 10。 尽管提供了更多聚合请求单元 (RU),但请增加连接数。 一般准则是每 200,000 RU 10 个连接。
  • 使用 Azure Cosmos DB 重试策略来处理间歇性限制响应。 有关详细信息,请参阅 Azure Cosmos DB 扩展库:
  • 对于多区域帐户,请在扩展中使用 Azure Cosmos DB 负载均衡策略。
  • 读取请求超时应设置为大于 1 分钟。 建议设置为 90 秒。

异常消息

如果在进行建议的更改后异常仍然存在,请查看接下来的三个部分中的异常消息。 如果错误日志包含这些异常消息中的任意一条,请按照该异常的建议操作。

BusyPoolException

此客户端错误指示已达到主机的最大请求连接数。 如果无法从队列中删除请求,可能会看到此错误。 如果每个主机的连接数已设置为最小值 10,则异常可能是由服务器端延迟较高导致。

Java driver v3 exception:
All host(s) tried for query failed (tried: :10350 (com.datastax.driver.core.exceptions.BusyPoolException: [:10350] Pool is busy (no available connection and the queue has reached its max size 256)))
All host(s) tried for query failed (tried: :10350 (com.datastax.driver.core.exceptions.BusyPoolException: [:10350] Pool is busy (no available connection and timed out after 5000 MILLISECONDS)))
C# driver 3:
All hosts tried for query failed (tried :10350: BusyPoolException 'All connections to host :10350 are busy, 2048 requests are in-flight on each 10 connection(s)')

建议

请确保将 max requests per connection 设置为最小值 10,而不是优化 connections per host。 请参阅代码示例部分

TooManyRequest(429)

如果请求速率过大,则会引发 OverloadException,当为表预配的吞吐量不足并且超出 RU 预算时,可能会发生此情况。 有关详细信息,请参阅大型请求服务器端重试

建议

应用以下选项之一:

  • 如果限制是永久性的,请增加预配的 RU。
  • 如果限制是间歇性的,请使用 Azure Cosmos DB 重试策略。
  • 如果无法引用扩展库,请启用服务器端重试

尝试查询的所有主机均失败

当客户端设置为连接到主要联系点区域以外的区域时,在启动的最初几秒钟内,你将收到以下异常消息之一:

  • 对于 Java 驱动程序 3:Exception in thread "main" com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (no host was tried)at cassandra.driver.core@3.10.2/com.datastax.driver.core.exceptions.NoHostAvailableException.copy(NoHostAvailableException.java:83)

  • 对于 Java 驱动程序 4:No node was available to execute the query

  • 对于 C# 驱动程序 3:System.ArgumentException: Datacenter China North does not match any of the nodes, available datacenters: China North 2

建议

Java 驱动程序 3Java 驱动程序 4 中使用 CosmosLoadBalancingPolicy。 此策略回退到指定本地数据不可用的主要写入区域的联系点。

注意

如果上述建议不能帮助解决你的问题,请联系 Azure Cosmos DB 支持。 请务必提供以下详细信息:异常消息、异常堆栈跟踪、datastax 驱动程序日志、通用故障时间、一致或间歇性故障、失败的键空间和表、失败的请求类型和 SDK 版本。

代码示例

Java 驱动程序 3 设置

   // socket options with default values
    // https://docs.datastax.com/en/developer/java-driver/3.6/manual/socket_options/
    SocketOptions socketOptions = new SocketOptions()
        .setReadTimeoutMillis(90000); // default 12000

    // connection pooling options (default values are 1s)
    // https://docs.datastax.com/en/developer/java-driver/3.6/manual/pooling/
    PoolingOptions poolingOptions = new PoolingOptions()
        .setCoreConnectionsPerHost(HostDistance.LOCAL, 10) // default 1
        .setMaxConnectionsPerHost(HostDistance.LOCAL, 10) // default 1
        .setCoreConnectionsPerHost(HostDistance.REMOTE, 10) // default 1
        .setMaxConnectionsPerHost(HostDistance.REMOTE, 10); //default 1

    // Azure Cosmos DB load balancing policy
    String Region = "China North";
    CosmosLoadBalancingPolicy cosmosLoadBalancingPolicy = CosmosLoadBalancingPolicy.builder()
        .withWriteDC(Region)
        .withReadDC(Region)
        .build();

    // Azure Cosmos DB retry policy
    CosmosRetryPolicy retryPolicy = CosmosRetryPolicy.builder()
        .withFixedBackOffTimeInMillis(5000)
        .withGrowingBackOffTimeInMillis(1000)
        .withMaxRetryCount(5)
        .build();

    Cluster cluster = Cluster.builder()
        .addContactPoint(EndPoint).withPort(10350)
        .withCredentials(UserName, Password)
        .withSSL(sslOptions)
        .withSocketOptions(socketOptions)
        .withPoolingOptions(poolingOptions)
        .withLoadBalancingPolicy(cosmosLoadBalancingPolicy)
        .withRetryPolicy(retryPolicy)
        .build();

Java 驱动程序 4 设置

    // driver configurations
    // https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/configuration/
    ProgrammaticDriverConfigLoaderBuilder configBuilder = DriverConfigLoader.programmaticBuilder();

    // connection settings
    // https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/pooling/
    configBuilder
        .withInt(DefaultDriverOption.CONNECTION_POOL_LOCAL_SIZE, 10) // default 1
        .withInt(DefaultDriverOption.CONNECTION_POOL_REMOTE_SIZE, 10) // default 1
        .withDuration(DefaultDriverOption.REQUEST_TIMEOUT, Duration.ofSeconds(90)) // default 2
        .withClass(DefaultDriverOption.RECONNECTION_POLICY_CLASS, ConstantReconnectionPolicy.class) // default ExponentialReconnectionPolicy
        .withBoolean(DefaultDriverOption.METADATA_TOKEN_MAP_ENABLED, false); // default true

    // load balancing settings
    // https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/load_balancing/
    String Region = "China North";
    List<String> preferredRegions = new ArrayList<String>();
    preferredRegions.add(Region);
    configBuilder
        .withClass(DefaultDriverOption.LOAD_BALANCING_POLICY_CLASS, CosmosLoadBalancingPolicy.class)
        .withBoolean(CosmosLoadBalancingPolicyOption.MULTI_REGION_WRITES, false)
        .withStringList(CosmosLoadBalancingPolicyOption.PREFERRED_REGIONS, preferredRegions);

    // retry policy
    // https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/retries/
    configBuilder
        .withClass(DefaultDriverOption.RETRY_POLICY_CLASS, CosmosRetryPolicy.class)
        .withInt(CosmosRetryPolicyOption.FIXED_BACKOFF_TIME, 5000)
        .withInt(CosmosRetryPolicyOption.GROWING_BACKOFF_TIME, 1000)
        .withInt(CosmosRetryPolicyOption.MAX_RETRIES, 5);

    CqlSession session = CqlSession.builder()
        .withSslContext(sc)
        .addContactPoint(new InetSocketAddress(EndPoint, Port))
        .withAuthCredentials(UserName, Password)
        .withLocalDatacenter(Region)
        .withConfigLoader(configBuilder.build())
        .build();

C# v3 驱动程序设置

    PoolingOptions poolingOptions = PoolingOptions.Create()
        .SetCoreConnectionsPerHost(HostDistance.Local, 10) // default 2
        .SetMaxConnectionsPerHost(HostDistance.Local, 10) // default 8
        .SetCoreConnectionsPerHost(HostDistance.Remote, 10) // default 1
        .SetMaxConnectionsPerHost(HostDistance.Remote, 10); // default 2

    SocketOptions socketOptions = new SocketOptions()
        .SetReadTimeoutMillis(90000); // default 12000

    buildCluster = Cluster.Builder()
        .AddContactPoint(Program.ContactPoint)
        .WithPort(Program.CosmosCassandraPort)
        .WithCredentials(Program.UserName, Program.Password)
        .WithPoolingOptions(poolingOptions)
        .WithSocketOptions(socketOptions)
        .WithReconnectionPolicy(new ConstantReconnectionPolicy(1000)) // default ExponentialReconnectionPolicy
        .WithSSL(sslOptions);

后续步骤