[英]How do I shutdown and reconfigure an AsyncHttpClient that is using NettyAsyncHttpProvider
我正在构建一个像这样的AsyncHttpClient
:
public AsyncHttpClient getAsyncHttpClient() {
AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder()
.setProxyServer(makeProxyServer())
.setRequestTimeoutInMs((int) Duration.create(ASYNC_HTTP_REQUEST_TIMEOUT_MIN, TimeUnit.MINUTES).toMillis())
.build();
return new AsyncHttpClient(new NettyAsyncHttpProvider(config), config);
}
这在启动时被调用一次,然后返回值传递并在各个地方使用。 makeProxyServer()
是我自己的函数,我的代理设置返回一个ProxyServer
对象。 我需要做的是能够更改代理服务器设置,然后重新创建AsyncHttpClient
对象。 但是,我不知道如何干净地关闭它。 一点点搜索让我相信close()
不是优雅的。 我担心每次代理设置更改时都会启动一个新的执行程序和一组线程。 这不会经常发生,但我的应用程序运行时很长。
我知道我可以为每个请求使用RequestBuilder.setProxyServer()
,但我想将它设置在一个位置,以便我的asyncHttpClient
实例的所有调用者都遵循系统范围的代理设置,而不需要每个开发人员都记得这样做。
什么是重新配置或拆卸和重建基于Netty
的AsyncHttpClient
的正确方法?
使用AsyncHttpClient.close()
的问题是它关闭了提供程序使用的线程池执行程序,然后没有重新构建它就无法重新使用客户端,因为根据文档 ,执行程序实例不能是ts关闭后重复使用。 所以,如果你采用这种方式,就没有办法重新构建客户端(除非你实现自己的ExecutorService,它将有另一个关闭逻辑,但它还有很长的路要走,恕我直言)。
但是,通过查看NettyAsyncHttpProvider
的实现,我可以看到它存储对给定AsyncHttpClientConfig
实例的引用,并调用其getProxyServerSelector()
来获取每个新的NettyAsyncHttpProvider.execute(Request...)
调用的代理设置(即AsyncHttpClient
执行的每个请求)。
然后,如果我们可以让getProxyServerSelector()
返回ProxyServerSelector
的可配置实例,那就可以了。
不幸的是, AsyncHttpClientConfig
被设计为只读容器,由AsyncHttpClientConfig.Builder
实例化。 为了克服这个限制,我们必须使用“换行/委托”方法来破解它:
创建一个派生自AsyncHttpClientConfig
的新类。 该类应该包装给定的单独的AsyncHttpClientConfig
实例,并实现AsyncHttpClientConfig
getter对该实例的委托。
为了能够在任何给定的时间点返回我们想要的代理选择器,我们在这个包装类中使这个设置变得可变,并为它公开setter。
例:
public class MyAsyncHttpClientConfig extends AsyncHttpClientConfig
{
private final AsyncHttpClientConfig config;
private ProxyServerSelector proxyServerSelector;
public MyAsyncHttpClientConfig(AsyncHttpClientConfig config)
{
this.config = config;
}
@Override
public int getMaxTotalConnections() { return config.maxTotalConnections; }
@Override
public int getMaxConnectionPerHost() { return config.maxConnectionPerHost; }
// delegate the others but getProxyServerSelector()
...
@Override
public ProxyServerSelector getProxyServerSelector()
{
return proxyServerSelector == null
? config.getProxyServerSelector()
: proxyServerSelector;
}
public void setProxyServerSelector(ProxyServerSelector proxyServerSelector)
{
this.proxyServerSelector = proxyServerSelector;
}
}
AsyncHttpClient
配置实例,并使用它来配置AsyncHttpClient
: 例:
MyAsyncHttpClientConfig myConfig = new MyAsyncHttpClientConfig(config);
return new AsyncHttpClient(new NettyAsyncHttpProvider(myConfig), myConfig);
myConfig.setProxyServerSelector(newSelector)
,客户端中的NettyAsyncHttpProvider
实例执行的新请求将使用新的代理服务器设置。 一些提示/警告:
这种方法依赖于NettyAsyncHttpProvider
的内部实现; 因此,在可维护性,未来的Netty库版本升级策略等方面做出自己的判断。在升级到新版本之前,您可以随时查看Netty源代码。 目前,我个人认为不太可能改变这个实现无效。
您可以使用com.ning.http.util.ProxyUtils.createProxyServerSelector(proxyServer)
获取ProxyServerSelector
的ProxyServer
- 这正是AsyncHttpClientConfig.Builder
所做的。
给定的示例没有用于访问proxyServerSelector
同步逻辑; 您可能希望根据应用程序逻辑需要添加一些。
也许这是一个好主意,提交功能请求AsyncHttpClient
能够建立一个“配置工厂”为AsyncHttpProvider
因此所有这些并发症会消失:-)
您应该为所有未完成的请求持有RequestHandle实例。 当你想要关闭时,你可以遍历并在所有这些上调用isFinished(),直到它们全部完成。 然后你就知道你可以安全地关闭它,并且没有任何待处理的请求被杀死。
一旦关闭,只需建立一个新的。 不要试图重用现有的。 如果您有对它的引用,请更改它们以引用将返回当前的Factory。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.