Apache Geode 服务器在负载测试期间偶尔 运行 断开连接

Apache Geode servers ocassionally run out of connections during load tests

下午好,

我们正在尝试将应用程序从 Redis 迁移到 Geode 集群以获得更好的可扩展性和多 WAN 同步。 目前我们只测试一个集群。设置为:

服务器设置:

--max-connections=1200 --J=-Xmx12G --J=-Xms12G --J=-XX:+UnlockExperimentalVMOptions
--J=-XX:+UseShenandoahGC --J=-XX:+DisableExplicitGC --J=-XX:+AlwaysPreTouch
--J=-Xlog:gc*:file=gc-%p-%t.log:uptime,time:filecount=3,filesize=10m --J=-Dgemfire.conserve-sockets=false

在负载测试期间,我们间歇性地(每小时一次)在服务器日志中遇到此错误:

[info 2019/11/18 16:46:03.561 PST <Pooled Waiting Message Processor 20> tid=0x925b] ...
[warn 2019/11/18 17:30:46.363 PST <Handshaker /XX.XXX.XXX.XXX:10001 Thread 152> tid=0xaed1] Rejected connection from /XX.XXX.XXX.XXX because current connection count of 1200 is greater than or equal to the configured max of 1200
[warn 2019/11/18 17:30:46.363 PST <Handshaker /XX.XXX.XXX.XXX:10001 Thread 155> tid=0xb503] Rejected connection from /XX.XXX.XXX.XXX because current connection count of 1200 is greater than or equal to the configured max of 1200
...[hundreds of these messages]

在客户上:

org.apache.geode.cache.client.ServerRefusedConnectionException: servername(servername:28165)<v145>:41001 refused connection: exceeded max-connections 1200
    at org.apache.geode.internal.cache.tier.sockets.Handshake.readMessage(Handshake.java:331)
    at org.apache.geode.cache.client.internal.ClientSideHandshakeImpl.handshakeWithServer(ClientSideHandshakeImpl.java:232)
    at org.apache.geode.cache.client.internal.ConnectionImpl.connect(ConnectionImpl.java:102)
    at org.apache.geode.cache.client.internal.ConnectionConnector.connectClientToServer(ConnectionConnector.java:71)
    at org.apache.geode.cache.client.internal.ConnectionFactoryImpl.createClientToServerConnection(ConnectionFactoryImpl.java:111)
    at org.apache.geode.cache.client.internal.pooling.ConnectionManagerImpl.createPooledConnection(ConnectionManagerImpl.java:202)
    at org.apache.geode.cache.client.internal.pooling.ConnectionManagerImpl.forceCreateConnection(ConnectionManagerImpl.java:212)
    at org.apache.geode.cache.client.internal.pooling.ConnectionManagerImpl.borrowConnection(ConnectionManagerImpl.java:319)
    at org.apache.geode.cache.client.internal.pooling.ConnectionManagerImpl.borrowConnection(ConnectionManagerImpl.java:70)

客户代码:

        ClientCacheFactory cacheFactory = new ClientCacheFactory()
                .set("log-level", "ERROR");
        for (String locator : locators) {
            HostPort hostPort = new HostPort(locator);
            cacheFactory.addPoolLocator(hostPort.getHost(), hostPort.getPort());
        }
        this.cache = cacheFactory.create();

然后是

    private <K,V> Region<K, V> getOrCreateRegion(String name, ClientRegionFactory<K, V> regionFactory) {
        Region<K, V> region = cache.getRegion(name);
        if (region == null) {
            region = regionFactory.create(name);
        }
        return region;
    }

要获取区域,未设置自定义选项。

每台服务器上的正常客户端连接数约为 250,但在负载测试期间的某个随机时间(60k 读取 RPS / 60k 写入 RPS) 连接数量跳到最大值 (1200),客户端无法打开连接。 分区区域的范围为 "distributed-ack",这会导致大量错误和数据损坏。 服务器在一两分钟内自愈,连接数下降到正常,但到那时测试失败了。 我尝试提高日志级别,但 "INFO" 什么也没显示(检查了受影响的服务器和定位器日志),"DEBUG" 生成了如此多的数据,以至于服务器无法跟上日志消息的泛滥。 120k 读写 RPS 对我们来说是正常的生产流量,用 10k 整体 RPS 测试没有出现异常。这些锁定与垃圾回收无关,因为 gc 日志显示在那段时间内没有 gc 运行

您对如何调整 Geode 集群以避免这些异常和数据损坏有任何想法吗?

发生此 "refused connection: exceeded max-connections" 错误是因为客户端正在尝试创建比您设置的最大连接数更多的服务器连接。

客户端使用连接池,因此来自单个客户端的并发连接数与当前正在从客户端执行操作的线程数成正比。

下一步是计算负载生成实际创建的线程数。从理论上讲,每个线程一次只能使用一个连接,所以如果负载非常不均匀并且所有客户端都以同时在同一台服务器上。

如果您无法控制客户端上的线程数,池本身具有调整参数,例如PoolFactory.setMaxConnections,这将限制来自单个客户端的连接数。