当前位置: 首页 > 知识库问答 >
问题:

泽西:在HTTP响应后关闭I/O资源

仲承福
2023-03-14

我的设置:我创建了一个REST服务(Jersey/Dropwizard),可以从数据库中流式传输大量内容。在GET操作期间,服务通过连接池接入数据库,将数据打包成流,并执行一些即时转换,以各种编码(CSV、JSON等)呈现请求的数据。数据库连接的生命周期与流的生命周期相关联,只有当流关闭时,数据库连接才会被释放。

流转换由编码器类执行,该类返回StreamingOutput,然后将其传递给响应对象。编码器当前处理流完全消耗时的资源关闭。

我的问题是:由于StreamingOutput没有实现AutoCloseable,当输出仅被部分消耗时,可能会发生连接泄漏。

我有时观察到,陈旧的活动连接正在连接池中堆积,我怀疑它们是由中止的HTTP连接引起的。如下所示,当前代码处理try块中发生的异常。我无法处理的是return语句之后发生的异常,我不知道如何将资源关闭的任何指令附加到响应对象。

我的问题是:在请求终止后(定期或由于错误),如何通知响应对象关闭特定资源?或者:当请求上下文结束时,有没有更好的方法来安全地关闭任何相关资源?

 @GET
 //@Produces(...)
 html" target="_blank">public Response streamData(
        @PathParam("key") String key,
        // ... other params
        ) {

    //decode and validate params
    Stream<Pojo> ps = null;
    try {
        // connect to db and obtain data stream for <key>
        ps = loadData(db, key);
        // apply detailed encoding instrunctions and create a StreamingOutput
        final StreamingOutput stream = Encoder.encodeData(ps, encodingArgs);
        return Response.ok(stream).build();
    } catch (Exception e) {
        closeOnException(ps); // wrapper for ps.close();
        throw e;
    }
 }

共有2个答案

班建义
2023-03-14

您可以在方法HttpServletResponse中添加:

@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Object streamData(
            @PathParam("key") String key,
            @Context HttpServletResponse response,
            // ... other params
            ) {
  ...
  response.getOutputStream().write(....)
  response.flushBuffer();
  response.getOutputStream().close();
  return null;
}
皇甫飞飙
2023-03-14

我从dropwizard邮件列表中收到了一个很好的答案,解决了我的问题,我想在这里引用它,以防有人遇到同样的问题。

https://groups.google.com/forum/#!topic/dropwizard用户/62GoLDBrQuo

引用肖恩的回答:

Jersey支持CloseableService,允许您在请求完成时注册要关闭的可关闭对象:

public Response streamData(..., @Context CloseableService closer) {
  ...
  closer.add(closeable);
  return Response.ok(...).build();
}
 类似资料:
  • 我想返回一个临时重定向,使用AsyncACK。 下面的“工作”(因为没有错误),但似乎不是异步的(它一次处理一个请求)。 这应该工作吗?如果我明确需要像https://jersey.github.io/documentation/latest/async.html#d0e9895一样启动一个新线程,返回响应是什么样子的?

  • 我试图理解异步响应在Jersey上的工作方式。我阅读了新泽西文档(https://jersey.java.net/documentation/latest/async.html)的第10章,但它对我的问题没有帮助。这里关于stackoverflow的研究也没有得出令人满意的答案(这一点我可以理解)。 我试图做的与本文中的一个问题类似(使用http状态202进行异步操作)。我想使用HTML表单文档将

  • 我使用的是Jersey客户端v2。16(Dropwizard 0.8.0的可传递依赖项,我也在使用它)。 当实体被读取为时,我不知何故对响应的关闭机制感到困惑。文件规定: 此外,如果实体被读入InputStream(通过response.readEntity(InputStream.class))中,则连接将保持打开状态,直到您完成对InputStream的读取。在这种情况下,应该在从InputS

  • 我决定在这部分替换Web.XML: 我指向servlet容器Jersey,它将接受对REST-Controllers的请求,表明在启动时有必要扫描路径com . skillsimprover . REST examples . REST上的包REST,并表明资源的所有方法和类的基URI都填充了/api/* 从 JAX-RS 2.x 版本开始,可以使用应用程序类或资源配置类来注册包和资源。 我执行了

  • 关于HTTP连接关闭,我有两个问题: > 如果一个客户端通过连接发送一个HTTP请求:靠近HTTP服务器,那么在客户端收到响应后,HTTP服务器还是客户端有责任发送TCP FIN? 如果客户端发送了一个格式错误的HTTP请求,而服务器发送了一个400错误的请求,那么最好的做法是通过服务器关闭连接(即使HTTP请求有connection:keep alive),还是保持连接仍然处于活动状态? 提前感

  • 当我在Jersey中有一个监听POST请求的方法,并且当我想从中获取数据的方法中有一个InputStream作为参数时,我需要关闭这个InputStream还是Jersey会处理这个问题? 我没有找到任何相关信息。不久前,我读过使用JAX-RS 2.0的RESTful Java,我不记得是否有人提到过它。现在浏览一下,我发现了几个代码示例,并且流没有关闭。我觉得没必要,但我想问问。