什么时候反应?

第二种方法。 服务器发送事件。

为了实现这种情况,我正在寻找一种通过MyBatis返回Observable的方法。 这意味着大量的调试,大量的试验和错误。 经过大约4个小时的快速浏览后,我发现MyBatis也可以返回Cursor(可迭代)。 那是我找到家的那一刻。 映射器代码变得简单:

让我们继续进行从Cursor到Observable的转换,并讨论一下Spring中服务器发送事件的实现。

在春季,sse由SseEmitter提供。 此类为我们提供了两种重要的方法-初始化和发送。

初始化由Spring调用。 一旦请求线程从控制器返回,它将设置处理程序,该处理程序执行编组并将数据发送到客户端。 在此之前,所有send方法调用都会将消息添加到内部SseEmitter的缓冲区中。

这对我们很重要,因为这意味着我们无法使用请求线程获取数据。 如果这样做,我们将在发送任何内容之前将所有数据添加到内部缓冲区,这将产生与我们尝试避免的OOM问题相同的问题。

结论是,不幸的是,我们需要使用线程池。

要注意的另一件事是,我们希望冷的Observable,以便我们在订阅和从数据库读取之间不跳过任何数据,并且需要手动管理事务,否则由于SqlSession关闭,mapper返回空的Cursor。 下面的代码捕获了以上所有内容:

剩下的就是我们的控制器:

您可能已经发现了两种MediaType,一种是用于整个流,另一种是用于消息。

也要注意超时。 默认设置各不相同,但是在tomcat 8上,您只有30秒钟来完成异步处理。 我将其设置为5分钟。

这就是实现。

结果

就数据集大小而言,CPU和内存使用率是恒定的。 CPU降落20%。 SSE最令人沮丧的是响应时间。 在许多情况下,它比第一种方法慢10倍 以列表形式返回数据。

尽管我没有在屏幕截图中包含该信息,但在测试后,full gc回收了所有内存,因此没有泄漏。 或者我还没有找到它们。

加特林。 服务器发送事件。
cdn.rawgit.com