有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

泽西岛2的java流媒体?

我一直在尝试让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());
}

然而jersey只是坐在那里,直到json生成器返回结果。我正在看charles proxy的结果

我需要启用某些功能吗?不知道为什么这不会流出来


编辑:

这可能真的有效,只是不是我所期望的。我不认为stream是在实时写东西,这正是我想要的,更多的是因为不必缓冲响应并立即将它们写出来给客户端。如果我运行一个一百万的循环,并且没有线程睡眠,那么数据确实会被分块写入,而不必在内存中缓冲


共 (1) 个答案

  1. # 1 楼答案

    你的编辑是正确的。它正在按预期工作StreamingOutput只是一个包装器,让我们直接写入响应流,但实际上并不意味着响应在每个服务器端写入流 而且AsyncResponse不会对客户机提供任何不同的响应。它只是帮助提高长时间运行任务的吞吐量。长时间运行的任务实际上应该在另一个线程中完成,因此该方法可以返回

    你似乎在寻找的是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导致了这个问题。一些名为“链接扫描程序”的功能阻止了这种分块过程的发生。我禁用了该功能,它开始工作

    我没有对分块进行过太多的探索,也不确定其安全含义,所以我不确定AVG应用程序为什么会有问题

    enter image description here


    编辑

    似乎真正的问题是由于缓冲响应以计算内容长度头。您可以查看this post了解如何改变这种行为