2013-11-13 2 views
5

Я построив AsyncHttpClient так:Как мне выключить и перенастроить AsyncHttpClient, который использует NettyAsyncHttpProvider

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?

+0

Хех, я просто для этого вопроса получил значок переползания. Как я уже упоминал в вопросе, я работал над этим, выполняя setProxyServer() для каждого запроса, но общая проблема, связанная с возможностью отключения и восстановления Netyn-based AsyncHttpClient, кажется, что это будет интересовать больше людей. – kbyrd

ответ

5

Проблема с использованием AsyncHttpClient.close() заключается в том, что он отключает исполнитель пула потоков, используемый поставщиком, тогда нет возможности повторно использовать клиент без его повторной сборки, поскольку в соответствии с documentation экземпляр исполнителя не может быть повторное использование после завершения ts. Таким образом, нет способа воссоздать клиента, если вы пойдете этим путем (если вы не реализуете собственный ExecutorService, у которого будет другая логика отключения, но это долгий путь, IMHO).

Однако из заглядывая в реализации NettyAsyncHttpProvider, я могу видеть, что он хранит ссылку на данный AsyncHttpClientConfig инстанции и называет его getProxyServerSelector() получить настройки прокси-сервера для каждого нового NettyAsyncHttpProvider.execute(Request...) вызова (то есть для каждого запроса, выполняемого AsyncHttpClient) ,

Тогда, если бы мы могли вернуть возвращаемый конфигурируемый экземпляр ProxyServerSelector, это сделало бы это.

К сожалению, AsyncHttpClientConfig предназначено для хранения только для чтения контейнера, созданного по лицензии AsyncHttpClientConfig.Builder. Чтобы преодолеть это ограничение, мы должны взломать его, используя, скажем, «обруча/делегат» подход:

  • Создайте новый класс, производный от AsyncHttpClientConfig. Класс должен обернуть данный отдельный экземпляр AsyncHttpClientConfig и реализовать делегирование AsyncHttpClientConfig геттеров к этому экземпляру.

  • Чтобы иметь возможность вернуть селектор прокси, который мы хотим в любой данный момент времени, мы делаем этот параметр изменяемым в этом классе-оболочке и выставляем для него установщик.

Пример:

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 перед обновлением до новой версии. В настоящий момент я лично считаю, что вряд ли слишком сильно изменится, чтобы аннулировать эту реализацию.

  • Вы можете получить ProxyServerSelector для ProxyServer с помощью com.ning.http.util.ProxyUtils.createProxyServerSelector(proxyServer) - это именно то, что делает AsyncHttpClientConfig.Builder.

  • В данном примере отсутствует логика синхронизации для доступа к proxyServerSelector; вы можете захотеть добавить некоторые из них в качестве логики приложения.

  • Может быть, это хорошая идея, чтобы отправить запрос на выделение для AsyncHttpClient, чтобы иметь возможность настроить «заводскую конфигурацию» для AsyncHttpProvider, так что все эти осложнения исчезнут :-)

+0

Фактически, AsyncHttpClientConfig имеет защищенное поле proxyServerSelector типа ProxyServerSelector; он может быть повторно использован в MyAsyncHttpClientConfig для сохранения измененного значения ProxyServerSelector. – NSH

0

У вас должен быть экземпляр RequestHandle для всех ваших незавершенных запросов. Когда вы хотите завершить работу, вы можете выполнить цикл и называть isFinished() для всех из них до тех пор, пока все они не будут выполнены. Тогда вы знаете, что можете безопасно закрыть его, и ожидаемые запросы не будут убиты.

Как только он закрыт, просто создайте новый. Не пытайтесь повторно использовать существующую. Если у вас есть ссылки на него, измените их для ссылки на Factory, которая вернет текущую.

+0

Кажется, что это должен быть комментарий к ответу о close(), а не совсем новый ответ. – kbyrd

+0

Отредактировано, чтобы рекомендовать «создать» новый объект вместо попытки повторного использования текущего. Упомянутая проблема заключалась в том, чтобы развернуть новых исполнителей, потому что это долгое время. Поскольку close остановит существующие (согласно @NSH), это не будет проблемой. –

 Смежные вопросы

  • Нет связанных вопросов^_^