在球衣 2 中流式传输?
Streaming in jersey 2?
我一直在尝试让 json 流媒体在 jersey 2 中工作。对于我来说,在流媒体完成之前,什么都不会流媒体。
我试过这个例子来模拟一个缓慢的数据生产者。
@Path("/foo")
@GET
public void getAsyncStream(@Suspended AsyncResponse response) {
StreamingOutput streamingOutput = output -> {
JsonGenerator jg = new ObjectMapper().getFactory().createGenerator(output, JsonEncoding.UTF8);
jg.writeStartArray();
for (int i = 0; i < 100; i++) {
jg.writeObject(i);
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
logger.error(e, "Error");
}
}
jg.writeEndArray();
jg.flush();
jg.close();
};
response.resume(Response.ok(streamingOutput).build());
}
然而球衣只是坐在那里,直到 json 生成器完成 return 结果。我正在查看 charles proxy 中的结果。
我需要启用某些功能吗?不知道为什么这不会流出
编辑:
这可能真的有效,只是不是我预期的那样。我不认为流正在实时写入东西,这正是我想要的,它更多的是不必缓冲响应并立即将它们写出给客户端。如果我 运行 一百万个循环并且没有线程休眠,那么数据确实会以块的形式写出,而不必在内存中缓冲。
您的编辑正确。它按预期工作。 StreamingOutput
只是一个包装器,让我们直接写入响应流,但实际上并不意味着响应在每个服务器端流式传输写入流。 另外 AsyncResponse
不就客户而言,提供任何不同的响应。它只是为了帮助提高长 运行 任务的吞吐量。长运行的任务其实应该在另一个线程中完成,所以方法可以return.
- 在 Asynchronous Server API
查看更多
您寻找的似乎是 Chunked Output
Jersey offers a facility for sending response to the client in multiple more-or-less independent chunks using a chunked output. Each response chunk usually takes some (longer) time to prepare before sending it to the client. The most important fact about response chunks is that you want to send them to the client immediately as they become available without waiting for the remaining chunks to become available too.
不确定它如何适用于您的特定用例,因为 JsonGenerator
需要 OutputStream
(我们使用的 ChuckedOutput
不是),但这里有一个更简单的例子
@Path("async")
public class AsyncResource {
@GET
public ChunkedOutput<String> getChunkedStream() throws Exception {
final ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
new Thread(() -> {
try {
String chunk = "Message";
for (int i = 0; i < 10; i++) {
output.write(chunk + "#" + i);
Thread.sleep(1000);
}
} catch (Exception e) {
} finally {
try {
output.close();
} catch (IOException ex) {
Logger.getLogger(AsyncResource.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}).start();
return output;
}
}
注意: 一开始我遇到了问题。我只会得到延迟的完整结果。问题似乎出在与程序完全不同的地方。实际上是我的 AVG 导致了问题。一些名为“LinkScanner”的功能阻止了这个分块过程的发生。我禁用了该功能,它开始工作了。
我没有深入研究分块,也不确定安全隐患,所以我不确定为什么 AVG 应用程序会出现问题。
编辑
似乎真正的问题是由于 Jersey 缓冲响应以计算 Content-Length header。您可以查看 this post 了解如何更改此行为
我一直在尝试让 json 流媒体在 jersey 2 中工作。对于我来说,在流媒体完成之前,什么都不会流媒体。
我试过这个例子来模拟一个缓慢的数据生产者。
@Path("/foo")
@GET
public void getAsyncStream(@Suspended AsyncResponse response) {
StreamingOutput streamingOutput = output -> {
JsonGenerator jg = new ObjectMapper().getFactory().createGenerator(output, JsonEncoding.UTF8);
jg.writeStartArray();
for (int i = 0; i < 100; i++) {
jg.writeObject(i);
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
logger.error(e, "Error");
}
}
jg.writeEndArray();
jg.flush();
jg.close();
};
response.resume(Response.ok(streamingOutput).build());
}
然而球衣只是坐在那里,直到 json 生成器完成 return 结果。我正在查看 charles proxy 中的结果。
我需要启用某些功能吗?不知道为什么这不会流出
编辑:
这可能真的有效,只是不是我预期的那样。我不认为流正在实时写入东西,这正是我想要的,它更多的是不必缓冲响应并立即将它们写出给客户端。如果我 运行 一百万个循环并且没有线程休眠,那么数据确实会以块的形式写出,而不必在内存中缓冲。
您的编辑正确。它按预期工作。 另外 StreamingOutput
只是一个包装器,让我们直接写入响应流,但实际上并不意味着响应在每个服务器端流式传输写入流。AsyncResponse
不就客户而言,提供任何不同的响应。它只是为了帮助提高长 运行 任务的吞吐量。长运行的任务其实应该在另一个线程中完成,所以方法可以return.
- 在 Asynchronous Server API 查看更多
您寻找的似乎是 Chunked Output
Jersey offers a facility for sending response to the client in multiple more-or-less independent chunks using a chunked output. Each response chunk usually takes some (longer) time to prepare before sending it to the client. The most important fact about response chunks is that you want to send them to the client immediately as they become available without waiting for the remaining chunks to become available too.
不确定它如何适用于您的特定用例,因为 JsonGenerator
需要 OutputStream
(我们使用的 ChuckedOutput
不是),但这里有一个更简单的例子
@Path("async")
public class AsyncResource {
@GET
public ChunkedOutput<String> getChunkedStream() throws Exception {
final ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
new Thread(() -> {
try {
String chunk = "Message";
for (int i = 0; i < 10; i++) {
output.write(chunk + "#" + i);
Thread.sleep(1000);
}
} catch (Exception e) {
} finally {
try {
output.close();
} catch (IOException ex) {
Logger.getLogger(AsyncResource.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}).start();
return output;
}
}
注意: 一开始我遇到了问题。我只会得到延迟的完整结果。问题似乎出在与程序完全不同的地方。实际上是我的 AVG 导致了问题。一些名为“LinkScanner”的功能阻止了这个分块过程的发生。我禁用了该功能,它开始工作了。
我没有深入研究分块,也不确定安全隐患,所以我不确定为什么 AVG 应用程序会出现问题。
编辑
似乎真正的问题是由于 Jersey 缓冲响应以计算 Content-Length header。您可以查看 this post 了解如何更改此行为