Jersey:HTTP 响应后关闭 I/O 资源
Jersey: Close I/O resources after HTTP response
我的设置: 我创建了一个 REST 服务 (Jersey/Dropwizard),它从数据库流式传输大量内容。在 GET 操作期间,服务通过连接池接入数据库,将数据包装到流中并执行一些即时转换以以各种编码(CSV、JSON、.. .).数据库连接的生命周期与流的生命周期相关,只有当流关闭时,数据库连接才会被释放。
流转换由编码器 class 执行,该编码器 return 是一个 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;
}
}
您可以将 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;
}
我从 dropwizard 邮件列表收到了一个很好的答案,它解决了我的问题,我想在这里引用它以防有人遇到同样的问题。
https://groups.google.com/forum/#!topic/dropwizard-user/62GoLDBrQuo
引用 Shawn 的回复:
Jersey 支持 CloseableService,允许您注册 Closeable 对象以在请求完成时关闭:
public Response streamData(..., @Context CloseableService closer) {
...
closer.add(closeable);
return Response.ok(...).build();
}
我的设置: 我创建了一个 REST 服务 (Jersey/Dropwizard),它从数据库流式传输大量内容。在 GET 操作期间,服务通过连接池接入数据库,将数据包装到流中并执行一些即时转换以以各种编码(CSV、JSON、.. .).数据库连接的生命周期与流的生命周期相关,只有当流关闭时,数据库连接才会被释放。
流转换由编码器 class 执行,该编码器 return 是一个 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;
}
}
您可以将 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;
}
我从 dropwizard 邮件列表收到了一个很好的答案,它解决了我的问题,我想在这里引用它以防有人遇到同样的问题。
https://groups.google.com/forum/#!topic/dropwizard-user/62GoLDBrQuo
引用 Shawn 的回复:
Jersey 支持 CloseableService,允许您注册 Closeable 对象以在请求完成时关闭:
public Response streamData(..., @Context CloseableService closer) {
...
closer.add(closeable);
return Response.ok(...).build();
}