Riak Java HTTPClientAdapter TCP CLOSE_WAIT

时间:2015-05-07 23:49:08

标签: rest spring-mvc tcp tomcat7 riak

TLDR:

OPEN_WAIT状态下有很多TCP连接关闭服务器

设定:

在Ubuntu12上安装了riak_1.2.0-1_amd64.deb Spring MVC 3.2.5 了Riak客户端 - 1.1.0.jar Tomcat7.0.51托管在Windows Server 2008 R2上 JRE6_45

完整说明:

如何确保Java RiakClient正确清理它与我没有留下大量CLOSE_WAIT tcp连接的连接?

我有一个Spring MVC应用程序,它使用Riak java客户端连接到远程实例/集群。

我们在托管Spring MVC应用程序的服务器上看到了很多TCP连接,这些连接在服务器无法连接到任何东西之前会继续构建,因为没有可用的端口。

重新启动Riak群集不会清除连接。

重新启动webapp会清除额外的连接。

我们正在使用HTTPClientAdapter和REST api。

当连接到关系数据库时,我通常会通过显式调用连接上的close,或者通过向池和事务管理器注册数据源,然后使用@Transactional注释我的服务来清理连接。

但是由于使用了HTTPClientAdapter,我原本期望它更像是一个HttpClient。 使用HttpClient,我将使用EntityUtils.consume(...)来使用Response实体,以确保正确清理所有内容。

HTTPClientAdapter确实有一个关机方法,我看到它在在线示例中被调用。 当我将方法调用跟踪到实际的RiakClient时,该方法为空。 此外,当我深入挖掘源代码时,它无处在关闭HttpResponse上的Stream或使用任何响应实体(与标准的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连接。

1 个答案:

答案 0 :(得分:0)

所以这已经差不多一年了,所以我想我会继续发布我是如何解决这个问题的。

解决方案是将我们使用的客户端实现更改为java客户端提供的HTTPClientAdapter,并传递配置以实现池和最大连接。以下是如何执行此操作的一些代码示例。

首先,我们使用的是旧版RIAK,所以这里是amven依赖:

cmd /c python hello.py

以下是这个例子:

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

我在实现中实际上打破了一点,并使用Spring注入值;我只想展示一个简化的例子。

通过将超时设置为小于标准的五分钟,系统将不会挂起连接太长时间(因此,5分钟+无论您设置超时的时间),这会导致连接器更快地进入close_wait状态

当然,设置池中的最大连接数可以防止应用程序打开数以万计的连接。