2

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

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

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

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

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

 @GET
 //@Produces(...)
 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;
    }
 }
4

2 回答 2

2

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

https://groups.google.com/forum/#!topic/dropwizard-user/62GoLDBrQuo

引用肖恩的回应:

Jersey 支持CloseableService,它允许您注册 Closeable 对象以在请求完成时关闭:

public Response streamData(..., @Context CloseableService closer) {
  ...
  closer.add(closeable);
  return Response.ok(...).build();
}
于 2019-03-23T12:36:32.220 回答
0

您可以将 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;
}
于 2018-11-22T14:44:01.870 回答