如何解决最大连接数超过的问题?

How to fix problem with max connections exceed?

我在异步模式下执行 Lua-函数并且我使用 NIOEventLoops。当我尝试获取下一个事件循环并执行 Lua-function 时,我遇到了一些异常:

com.aerospike.client.AerospikeException$Connection: Error -7 from BB967EF43270008 127.0.0.1 3000: Node BB967EF43270008 127.0.0.1 3000 event loop 5 max connections 100 would be exceeded.
   at com.aerospike.client.cluster.Node.getAsyncConnection(Node.java:657) ~[aerospike-client-4.2.2.jar:?]
   at com.aerospike.client.async.NioCommand.executeCommand(NioCommand.java:184) [aerospike-client-4.2.2.jar:?]
   at com.aerospike.client.async.NioCommand.run(NioCommand.java:146) [aerospike-client-4.2.2.jar:?]
   at com.aerospike.client.async.NioEventLoop.registerCommands(NioEventLoop.java:211) [aerospike-client-4.2.2.jar:?]
   at com.aerospike.client.async.NioEventLoop.runCommands(NioEventLoop.java:173) [aerospike-client-4.2.2.jar:?]
   at com.aerospike.client.async.NioEventLoop.run(NioEventLoop.java:156) [aerospike-client-4.2.2.jar:?]
   at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]

这是我获取下一个事件循环的方法:

 private synchronized EventLoop getNextEventLoop() {
        EventLoop next;
        do {
            next = eventLoops.next();
        } while (next.getProcessSize() >= maxConnectionsPerEventLoop);
        return next;
    }

这就是我执行 Lua 函数的方式:

as.execute(getNextEventLoop()
                , new ExecuteListener() {
                    @Override
                    public void onSuccess(Key key, Object obj) {

                       ...
                    }

                    @Override
                    public void onFailure(AerospikeException exception) {
                       ...
                    }
                }
                , writePolicy
                , key
                , "lua-pack"
                , "funcName"
                , Value.get(binName), Value.get(value)
        );

如何避免这种异常?

您已达到 ClientPolicy.maxConnsPerNode 上限。对于 500 maxConnsPerNode 和 5 个事件循环,每个事件循环可以为每个节点使用最多 100 (500/5) 个连接。我假设您的 maxConnectionsPerEventLoop 值 >= 100。此外,不能保证在调用 getProcessSize() 后将下一个命令发送到事件循环时插槽仍然可用。

解决方案是在每个事件循环上限制 maxCommandsInProcess。这是限制飞行命令(以及连接)的线程安全方式。

EventPolicy eventPolicy = new EventPolicy();
eventPolicy.maxCommandsInProcess = 100;  // max 100 commands per event loop.
eventPolicy.maxCommandsInQueue = 0;      // unbounded queue

int eventLoopSize = 5;
EventLoops eventLoops = new NioEventLoops(eventPolicy, eventLoopSize);

ClientPolicy clientPolicy = new ClientPolicy();
clientPolicy.eventLoops = eventLoops;
clientPolicy.maxConnsPerNode = eventPolicy.maxCommandsInProcess * eventLoopSize;

当达到 maxCommandsInProcess 限制时,异步命令队列用于命令。如果传入命令的速率始终超过处理命令的速率,那么您的应用程序可能 运行 内存不足。为避免这种情况,您可能需要限制队列大小。

eventPolicy.maxCommandsInQueue = 10000;

如果达到此队列大小,将抛出 AerospikeException.AsyncQueueFull 异常。您的应用程序应通过在非事件循环线程中延迟命令来响应,直到 eventLoop.getQueueSize() 足够低。