当前位置: 首页 > 知识库问答 >
问题:

Jersey客户端,带有用于池的Apache连接器(性能)

屈博
2023-03-14

我们有一个泽西客户端,基本配置:

public class HttpClient {

    private transient final WebTarget target;

    public HttpClient(final String host, final int port, final String path, final int requestTimeout) {
        final URI uri = UriBuilder.fromUri("http://" + host).port(port).build();
        final Client client = ClientBuilder.newClient();

        client.property(ClientProperties.READ_TIMEOUT, requestTimeout);
        target = client.target(uri).path(path);
    }

    public byte[] makeRequest(final byte[] request) throws HsmException {
        try {
            return target.request()
                    .accept(MediaType.APPLICATION_OCTET_STREAM)
                    .post(Entity.entity(request, MediaType.APPLICATION_OCTET_STREAM), byte[].class);
        }
        catch (Exception e) {
            // Box JAX-RS exceptions as they get weirdly handled by the outer Jersey layer.
            throw new Exception("Could not make request: " + e.getMessage(), e);
        }
    }

}

现在,有了这个客户端,我们每秒可以发出大约900个请求。所以在我试图获得更好的结果的时候,我考虑了实现池,使用ApacheHttp客户端和泽西连接器,像这样:

public class HttpClient {
    private transient final WebTarget target;

    public HttpClient(final String host, final int port, final String path, final int requestTimeout) {
        final ClientConfig clientConfig = new ClientConfig();
        clientConfig.property(ClientProperties.READ_TIMEOUT, requestTimeout);
        clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 500);

        final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(150);
        connectionManager.setDefaultMaxPerRoute(40);
        connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost(host)), 80);

        clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);

        final ApacheConnectorProvider connector = new ApacheConnectorProvider();
        clientConfig.connectorProvider(connector);

        final URI uri = UriBuilder.fromUri("http://" + host).port(port).build();
        final Client client = ClientBuilder.newClient(clientConfig);
        target = client.target(uri).path(path);
    }

    @Override
    public byte[] makeRequest(final byte[] request) throws HsmException {
        try {
            return target.request()
                    .accept(MediaType.APPLICATION_OCTET_STREAM)
                    .post(Entity.entity(command, MediaType.APPLICATION_OCTET_STREAM), byte[].class);
        }
        catch (Exception e) {
            // Box JAX-RS exceptions as they get weirdly handled by the outer Jersey layer.
            throw new Exception("Could not make request:" + e.getMessage(), e);
        }
    }
}

结果完全一样,大约每秒900个请求。

我没有受到CPU、ram、磁盘等的限制。我找不到瓶颈。我在设置连接管理器时测试了多个值,但结果完全相同。

我遗漏了什么吗?还有其他我遗漏的参数吗?我用错了方法吗?

共有1个答案

田慈
2023-03-14

您可以尝试使用httpasyncclient进行HTTP连接池。

httpclient对连接池使用线程阻塞I/O,这意味着负责发送HTTP请求的线程也负责处理HTTP响应。同时,线程仍然在套接字上阻塞。

相反,http pasyncClient是一个完全异步的HTTP客户端处理程序,它基于JavaNIO(非阻塞)I/O模型,允许库用户从非阻塞HTTP连接流式传输消息内容。

 类似资料:
  • 执行kafka客户端的生产者/消费者连接池有意义吗? kafka是否在内部维护已初始化并准备好使用的连接对象列表? 我们希望最小化连接创建的时间,这样在发送/接收消息时就不会有额外的开销。 目前,我们正在使用apache共享池库来保持连接。 任何帮助都将不胜感激。

  • 问题内容: 我正在设计一个将Redis用作数据库的Web服务,并且我想了解使用Redis与StackService客户端连接的最佳实践。 关键是我一直在阅读有关Redis的文章,发现与服务器交互的最佳方法是使用单个并发连接。 问题是,尽管每当Web客户端向Web服务发出请求时,我都会使用 PooledRedisClientManager ,但我又获得了一个到Redis服务器的连接客户端(打开的连接

  • 我试图理解netty http客户端连接池。如果是NIO和异步的,那么这个连接池的意义是什么? 例如:如果服务A调用服务B,并且服务A的客户端连接池计数设置为50,那么这是否意味着我们最多只能发出50个并行请求? 更新: 我在3.5秒内完成了所有通话。理想情况下,有一个连接,我应该在150秒内完成。

  • 问题内容: 我在生产中看到很多连接重置,可能有多种原因,但我想确保代码中没有连接泄漏。我在代码中使用Jersey客户端 最初,我以以下方式实例化客户端Client this.client = Client.create(),我们将其更改为ApacheHttpClient.create()。我没有在响应上调用close(),但是我假设ApacheHttpClient将在内部执行该操作,因为HttpC

  • 客户端应用程序在以下代码处挂起:

  • 我对Google Cloud Bigtable做了一个负载测试,制作了一个虚拟的web应用程序,用于处理向Bigtable写入数据和从Bigtable读取数据的请求。一开始,我只使用一个Bigtable连接作为单例,并跨所有线程(请求)重用它。当我增加请求数量时,我注意到性能正在变慢。不知何故,我没有增加节点的数量,而是想到了创建多个Bigtable连接,然后将它们随机分配给任何线程,从而提高了性