如何保持固定的连接数

时间:2017-02-03 03:43:12

标签: java multithreading performance network-programming threadpool

我是Java的新手,但对于一般编程并不陌生。

场景是我一次最多可以有n个连接,而打开和关闭连接的成本非常高。

我想重复使用相同的n个连接,并希望在Collection中保留一些内容。

当请求到来时,我会选择连接,完成工作并返回连接而不关闭。当下一个请求到来时,我会选择下一个可用的连接。

当所有连接都被使用并且请求到来时,我只是等待连接可用。

什么是最干净的Java解决方案。我不需要代码,我只需要一些想法来探索。可能是某些框架已经做到了,可能是某些java类已经提供了那个功能。

非常感谢任何想法。

4 个答案:

答案 0 :(得分:0)

我建议你选择连接池。在这种情况下,如果您将Connection用于多个任务,请将它们分别写入池中。 在需要时从池中获取连接。然后在完成后将其推回池中。通过这种方式,Connection将是线程安全的,并且可以避免不一致。 此外,打开和关闭连接将导致资源紧缩。

答案 1 :(得分:0)

使用HTTP Core NIO或Netty等框架来执行此操作。对于HTTPCore NIO的示例实例,您可以创建一个工作线程组以连接到后端,如下所示。

ProxyConnPool connPool = createConnectionPool(connectingIOReactor);
connPool.setMaxTotal(100);
connPool.setDefaultMaxPerRoute(20);

private static ProxyConnPool createConnectionPool(final ConnectingIOReactor connectingIOReactor)
                                                                                                    throws KeyManagementException,
                                                                                                    KeyStoreException,
                                                                                                    NoSuchAlgorithmException,
                                                                                                    CertificateException,
                                                                                                    FileNotFoundException,
                                                                                                    IOException {
        ProxyConnPool proxyConnPool = null;

        if (SECURE_BACKEND) {
            clientSSLContext =
                               SSLUtil.createClientSSLContext(TRUST_STORE_LOCATION,
                                                              TRUST_STORE_PASSWORD);

            BasicNIOConnFactory connectionFactory =
                                                    new BasicNIOConnFactory(
                                                                            clientSSLContext,
                                                                            null,
                                                                            ConnectionConfig.DEFAULT);

            proxyConnPool = new ProxyConnPool(connectingIOReactor, connectionFactory, 5000);
        } else {
            proxyConnPool = new ProxyConnPool(connectingIOReactor, ConnectionConfig.DEFAULT);
        }

        return proxyConnPool;
    }

您可以找到HTTP core NIO reverse proxyNetty reverse Proxy

的示例代码

在Netty中,代码与此类似。

// Configure the bootstrap.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

希望这会有所帮助。快乐的编码!

答案 2 :(得分:0)

  

当请求到来时,我会选择连接,完成工作并返回连接而不关闭。当下一个请求到来时,我会选择下一个可用的连接。

我会使用一个由所有线程共享的简单BlockingQueue<Connection>

final BlockingQueue<Connection> connectionQueue = new LinkedBlockingQueue<Connection>();

在应用程序启动时,您将打开一堆Connection个对象并将它们添加到队列中。

for (int i = 0; i < NUM_CONNECTIONS_TO_START; i++) {
    queue.put(new Connection());
}

当线程获得连接时,它将从队列中获得Connection,如果没有立即可用,则等待一个。{1}}。在使用Connection之后,它会将其返回到队列以供下一个线程使用。

// this will wait if there are no connections available
Connection connection = queue.take();
try {
   useTheConnection(connection);
} finally {
   // after we are done add it back to the queue
   queue.put(connection);
}

所有这一切的棘手部分是当你在套接字上得到某种网络异常时。您的线程需要正确关闭Connection,然后将新的一个添加到队列中。也许是这样的:

// this will wait if there are no connections available
Connection connection = queue.take();
try {
   useTheConnection(connection);
} catch (Exception e) {
   // assume the connection is bad
   try {
      connection.close();
   } catch (Exception e2) {
      // ignore any exceptions here
   }
   // start a new fresh connection to add back to our queue
   connection = new Connection();
} finally {
   // after we are done add it back to the queue
   queue.put(connection);
}

答案 3 :(得分:-1)

您可以使用具有固定线程数的Executor Service

ExecutorService service = Executors.newFixedThreadPool(n);

您可以创建一个类Connection,它将创建一个连接对象并将其返回

class Connection implements Callable<Connection> {

    @Override
    public Connection call() {
        // Logic to get the connection
        return new Connection();
    }
}

然后提交任务并从池中获取Connection的Future对象。

Future<Connection> future = service.submit(new Connection());
Connection conn = future.get();