Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何关闭并重新配置使用NettyAsyncHttpProvider的AsyncHttpClient_Java_Netty_Asynchttpclient - Fatal编程技术网

Java 如何关闭并重新配置使用NettyAsyncHttpProvider的AsyncHttpClient

Java 如何关闭并重新配置使用NettyAsyncHttpProvider的AsyncHttpClient,java,netty,asynchttpclient,Java,Netty,Asynchttpclient,我正在构建一个AsyncHttpClient,如下所示: public AsyncHttpClient getAsyncHttpClient() { AsyncHttpClientConfig config = new AsyncHttpClientConfig.Builder() .setProxyServer(makeProxyServer()) .setRequestTimeoutInMs((int)

我正在构建一个
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
的正确方法是什么?

您应该为所有未完成的请求保留一个RequestHandle实例。当您想关闭时,可以循环并对所有这些文件调用isFinished(),直到它们全部完成。然后您知道您可以安全地关闭它,并且不会杀死任何挂起的请求


一旦它关闭了,就建一个新的。不要试图重复使用现有的。如果您周围有对它的引用,请将这些引用更改为引用将返回当前工厂的工厂。

使用
AsyncHttpClient.close()
的问题在于它关闭了提供程序使用的线程池执行器,然后在不重新构建它的情况下无法重新使用客户端,因为根据,ts关闭后,无法重用executor实例。因此,如果这样做的话,就只能重新构建客户端(除非您实现自己的ExecutorService,该服务将具有另一个关闭逻辑,但还有很长的路要走,IMHO)

但是,通过查看
NettyAsyncHttpProvider
的实现,我可以看到它存储了对给定
AsyncHttpClientConfig
实例的引用,并调用其
getProxyServerSelector()
来获取每个新
NettyAsyncHttpProvider.execute(请求…
调用)的代理设置(即对于
AsyncHttpClient
执行的每个请求)

然后,如果我们可以让
getProxyServerSelector()
返回
ProxyServerSelector
的可配置实例,那么就可以了

不幸的是,
AsyncHttpClientConfig
被设计为只读容器,由
AsyncHttpClientConfig.Builder
实例化。 为了克服这一限制,我们必须破解它,比如说,使用“wrap/delegate”方法:

  • 创建一个新类,该类派生自
    AsyncHttpClientConfig
    。该类应包装给定的单独
    AsyncHttpClientConfig
    实例,并将
    AsyncHttpClientConfig
    getter委托给该实例

  • 为了能够在任何给定的时间点返回所需的代理选择器,我们在this包装器类中使此设置可变,并为其公开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;
  }
}
MyAsyncHttpClientConfig myConfig = new MyAsyncHttpClientConfig(config); 
return new AsyncHttpClient(new NettyAsyncHttpProvider(myConfig), myConfig);
  • 现在,在您的示例中,使用新的包装器包装您的
    AsyncHttpClient
    config实例,并使用它配置
    AsyncHttpClient
例如:

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;
  }
}
MyAsyncHttpClientConfig myConfig = new MyAsyncHttpClientConfig(config); 
return new AsyncHttpClient(new NettyAsyncHttpProvider(myConfig), myConfig);
  • 无论何时调用myConfig.setProxyServerSelector(newSelector),客户机中的
    NettyAsyncHttpProvider
    实例执行的新请求都将使用新的代理服务器设置
一些提示/警告:

  • 这种方法依赖于
    nettysynchttpprovider
    的内部实现;因此,您可以对可维护性、未来Netty库版本升级策略等做出自己的判断。在升级到新版本之前,您可以随时查看Netty源代码。目前,我个人认为不太可能更改过多将使此实现无效

  • 通过使用
    com.ning.http.util.ProxyUtils.createProxyServerSelector(ProxyServer)
    ,您可以为
    ProxyServer
    获取
    ProxyServerSelector
    ——这正是
    AsyncHttpClientConfig.Builder
    所做的

  • 给定的示例没有用于访问
    proxyServerSelector
    的同步逻辑;您可能需要根据应用程序逻辑的需要添加一些同步逻辑

  • AsyncHttpClient
    提交一个功能请求,以便能够为
    AsyncHttpProvider
    设置一个“配置工厂”,这样所有这些复杂情况都会消失,这可能是一个好主意:-)


嘿,我刚刚拿到了这个问题的风滚草徽章。正如我在问题中提到的,我通过对每个请求执行setProxyServer()来解决这个问题,但是能够关闭并重建基于Netty的AsyncHttpClient的总体问题似乎会引起更多人的兴趣。这似乎应该是对close()答案的评论,而不是一个全新的答案。编辑以推荐“building”创建新对象,而不是尝试重新使用当前对象。提到的担心是围绕着新的执行者的旋转,因为这是一个长寿命的应用程序。由于close将停止现有的字段(根据@NSH),因此这不会是一个问题;可以在MyAsyncHttpClientConfig中重新使用它来存储可变的ProxyServerSelector值。