如何缓存Java中的httpclient对象?

How to cache the httpclient object in Java?

在我的客户端 webapp 中使用 Apache HttpClient 4.5.x 连接到(并登录)另一个(比如主)服务器 webapp。

这两个 webapp 之间的关系是多对多的 - 这意味着 some 用户在客户端 webapp 中的请求,它必须以 another 用户 + 在服务器 webapp 中进行休息呼叫。因此,需要对 cookiestores 进行一些分离,并且在创建 httpclient 实例后无法(有吗?)get/set cookie store,因此客户端 webapp 中收到的每个请求线程都可以像这样(需要优化):

HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(new BasicCookieStore()).build();
//Now POST to login end point and get back JSESSIONID cookie and then make one REST call, and then the client object goes out of scope when the request ends.

我希望询问缓存 httpclient 实例对象的最佳实践,因为它很重并且应该至少被多个请求重用,如果不是作为静态单例用于整个客户端 webapp。

具体来说,我希望就以下哪些(如果有的话)方法构成最佳实践提出建议:

  1. 使用静态 ConcurrentHashMap 为客户端 webapp 中的每个 "user" 缓存 httpclient 及其关联的 basiccookiestore,并仅在包含时登录缓存的 cookie 即将过期。不确定内存使用情况,并且 un/rarely-used httpclient 保留在内存中而不会被驱逐。

  2. 仅缓存 Cookie(以某种方式),但在需要使用该 cookie 进行 rest 调用时重新创建一个新的 httpclient 对象。这会保存之前的登录调用,直到 cookie 过期,但不会重用 htptclient。

  3. PooledConnectionManager - 但无法轻松找到示例,尽管可能需要设计驱逐策略、最大线程数等(因此可能很复杂) .

有更好的方法吗?谢谢。

参考文献:

Generally it is recommended to have a single instance of HttpClient per communication component or even per application

使用并发哈希映射将是实现您想要执行的操作的最简单方法。

此外,如果您正在使用 Spring,您可能需要创建一个用于保存 HTTP 客户端的 bean。

你为什么要做这一切?可以使用本地 HttpContext 在每个请求的基础上分配不同的 CookieStore

如果需要,可以为每个唯一用户维护 CookieStore 个实例的映射。

CloseableHttpClient httpclient = HttpClients.createDefault();
CookieStore cookieStore = new BasicCookieStore();

// Create local HTTP context
HttpClientContext localContext = HttpClientContext.create();
// Bind custom cookie store to the local context
localContext.setCookieStore(cookieStore);

HttpGet httpget = new HttpGet("http://httpbin.org/cookies");
System.out.println("Executing request " + httpget.getRequestLine());

// Pass local context as a parameter
CloseableHttpResponse response = httpclient.execute(httpget, localContext);
try {
    System.out.println("----------------------------------------");
    System.out.println(response.getStatusLine());
    List<Cookie> cookies = cookieStore.getCookies();
    for (int i = 0; i < cookies.size(); i++) {
        System.out.println("Local cookie: " + cookies.get(i));
    }
    EntityUtils.consume(response.getEntity());
} finally {
    response.close();
}