2015-05-07 7 views
0

TLDR:Riak Java HTTPClientAdapter TCP CLOSE_WAIT

Множество TCP соединений в состоянии OPEN_WAIT будет отключена сервер

установки:

riak_1.2.0-1_amd64.deb установлен на Ubuntu12 Spring MVC 3.2.5 riak-client-1.1.0.jar Tomcat7.0.51 размещен на Windows Server 2008 R2 JRE6_45

Полное описание:

Как убедиться, что Java RiakClient правильно очистки это подключение к, что я не ушел с обилием соединений TCP CLOSE_WAIT?

У меня есть приложение Spring MVC, которое использует клиент Riak java для подключения к удаленному экземпляру/кластеру.

Мы видим много TCP-соединений на сервере, на котором размещено приложение Spring MVC, которое продолжает расти до тех пор, пока сервер больше не сможет подключиться к чему-либо, потому что нет доступных портов.

Перезапуск кластера Riak не очищает соединения вверх.

Перезапуск webapp очищает дополнительные подключения.

Мы используем HTTPClientAdapter и REST api.

При подключении к реляционной базе данных я обычно очищал бы соединения, либо явным образом закрывая соединение, либо регистрируя источник данных с помощью пула и диспетчера транзакций, а затем аннотируя мои службы с помощью @Transactional.

Но так как с помощью HTTPClientAdapter я ожидал, что это больше похоже на HttpClient. С HttpClient я бы использовал объект Response с EntityUtils.consume (...), чтобы убедиться, что все правильно очищено.

HTTPClientAdapter имеет метод выключения, и я вижу, что он вызывается в онлайн-примерах. Когда я проследил вызов метода до фактического RiakClient, метод пуст. Кроме того, когда я копаю исходный код, нигде в нем он никогда не закрывает поток на HttpResponse или не потребляет никакой объект ответа (как со стандартным примером Apache EntityUtils).

Вот пример того, как выполняются вызовы.

 private RawClient getRiakClientFromUrl(String riakUrl) { 
    return new HTTPClientAdapter(riakUrl); 
    } 


    public IRiakObject fetchRiakObject(String bucket, String key, boolean useCache) { 

     try { 
     MethodTimer timer = MethodTimer.start("Fetch Riak Object Operation"); 
     //logger.debug("Fetching Riak Object {}/{}", bucket, key); 
     RiakResponse riakResponse; 
     riakResponse = riak.fetch(bucket, key); 
     if(!riakResponse.hasValue()) { 
      //logger.debug("Object {}/{} not found in riak data store", bucket, key); 
      return null; 
     } 

     IRiakObject[] riakObjects = riakResponse.getRiakObjects(); 
     if(riakObjects.length > 1) { 
      String error = "Got multiple riak objects for " + bucket + "/" + key; 
      logger.error(error); 
      throw new RuntimeException(error); 
     } 

     //logger.debug("{}", timer); 
     return riakObjects[0]; 
     } 
     catch(Exception e) { 
     logger.error("Error fetching " + bucket + "/" + key, e); 
     throw new RuntimeException(e); 
     } 
    } 

Единственный вариант я могу думать, чтобы создать RiakClient отдельно от адаптера, так что я могу получить доступ к HttpClient и затем ConnectionManager.

В настоящее время я работаю над переключением на PBClientAdapter, чтобы узнать, может ли это помочь, но для целей этого вопроса (а потому, что остальная часть команды может не нравиться мне переключать по какой-либо причине), допустим, что я должен продолжать подключаться через HTTP.

+0

Независимо от того, что «RiakClient», он должен закрыть или отключить или отпустить или что-то еще, что вы не вызываете. – EJP

+0

Да, это так. «HTTPClientAdapter имеет метод выключения, и я вижу, что он вызывается в онлайн-примерах. Когда я прослеживал вызов метода к фактическому RiakClient, метод пуст». Свяжите поворот java-riak-ckient в github: https : //github.com/basho/riak-java-client – Pytry

ответ

0

Так что прошло почти год, поэтому я подумал, что буду идти дальше и публиковать, как я решил эту проблему.

Решение заключалось в том, чтобы изменить реализацию клиента, которую мы использовали, в HTTPClientAdapter, предоставляемый java-клиентом, передавая конфигурацию для реализации пулов и максимальных соединений. Вот пример кода, как это сделать.

Во-первых, мы на старой версии Riak, так вот amven зависимость:

<dependency> 
    <groupId>com.basho.riak</groupId> 
    <artifactId>riak-client</artifactId> 
    <version>1.1.4</version> 
</dependency> 

И вот пример:

public RawClient riakClient(){ 

    RiakConfig config = new RiakConfig(riakUrl); 
    //httpConnectionsTimetolive is in seconds, but timeout is in milliseconds 
    config.setTimeout(30000); 
    config.setUrl("http://myriakurl/); 
    config.setMaxConnections(100);//Or whatever value you need 

    RiakClient client = new RiakClient(riakConfig); 

    return new HTTPClientAdapter(client); 
} 

Я на самом деле сломал, что немного в моей реализации и использовал Spring для ввода значений; Я просто хотел показать упрощенный пример.

Установив тайм-аут на что-то меньшее, чем стандартные пять минут, система не будет слишком долго висеть на соединениях (так что 5 минут + все, что вы установите для таймаута), что заставляет connectiosn вводить статус close_wait рано.

И, конечно, установка максимальных соединений в пуле предотвращает открытие приложения из 10 тысяч подключений.

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

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