Java8 数据库请求的流式或反应式/观察器
Java8 Stream or Reactive / Observer for Database Requests
我正在重新考虑我们的 Spring MVC 应用程序行为,是从数据库中 pull (Java8 Stream) 数据还是让数据库更好push (Reactive / Observable) 它是数据并使用背压来控制数量。
现状:
User
请求 30 篇最新文章
Service
执行数据库查询并将 30 个结果放入 List
Jackson
遍历 List
并生成 JSON 响应
为什么要切换实现?
这非常耗费内存,因为我们一直将这 30 个对象保存在内存中。这不是必需的,因为应用程序一次处理一个对象。虽然应用程序应该能够检索一个对象、处理它、丢弃它并获取下一个对象。
Java8 流? (拉)
使用 java.util.Stream
这很容易:Service
创建一个 Stream
,它在后台使用数据库游标。每次 Jackson
为 Stream
的一个元素写入 JSON 字符串时,它会请求下一个,然后触发数据库游标到 return 下一个条目。
RxJava/响应式/可观察? (推)
这里我们有相反的情况:数据库必须逐个条目推送并且 Jackson
必须为每个元素创建 JSON 字符串,直到 onComplete
方法被调用.
即Controller
告诉 Service
:给我一个 Observable<Article>
。然后 Jackson
可以请求尽可能多的数据库条目。
分歧与关注:
使用 Streams
在 请求下一个数据库条目和检索/处理它 之间总会有一些延迟。如果网络连接速度慢或必须发出大量数据库请求才能完成响应,这可能会减慢 JSON 响应时间。
使用RxJava
应该总是有数据可供处理。如果太多,我们可以使用背压来减慢从数据库到应用程序的数据传输。在最坏的情况下,buffer/queue 将包含 所有 请求的数据库条目。那么内存消耗将等于我们当前使用 List
.
的解决方案
我为什么要问/我在问什么?
我错过了什么?还有其他优点/缺点吗?
为什么(特别是)Spring 数据团队扩展他们的 API 以支持来自数据库的 Stream
响应,如果总是有(短)延迟每个数据库之间request/response?对于大量请求的条目,这可能会导致一些明显的延迟。
对于这种情况,是否建议使用 RxJava
(或其他一些反应性实现)?还是我遗漏了什么缺点?
您似乎在谈论底层数据库引擎的提取大小。
如果将其减少到一个(一次获取和处理一行),是的,您将在请求时间内节省一些 space...
但是拥有合理的块大小通常是有意义的。
如果它太小,你将有很多昂贵的网络往返。如果块大小太大,您将面临 运行 内存不足的风险,或者每次提取都会引入过多的延迟。所以这是一种妥协,正确的 chunk/fetch 大小取决于您的具体用例。
关于反应式与否,我认为这无关紧要。与 RxJava 和 Cassandra 一样,可以从异步结果集创建一个 Observable,这取决于查询(配置)一次应该获取和推送多少项。
我正在重新考虑我们的 Spring MVC 应用程序行为,是从数据库中 pull (Java8 Stream) 数据还是让数据库更好push (Reactive / Observable) 它是数据并使用背压来控制数量。
现状:
User
请求 30 篇最新文章Service
执行数据库查询并将 30 个结果放入List
Jackson
遍历List
并生成 JSON 响应
为什么要切换实现?
这非常耗费内存,因为我们一直将这 30 个对象保存在内存中。这不是必需的,因为应用程序一次处理一个对象。虽然应用程序应该能够检索一个对象、处理它、丢弃它并获取下一个对象。
Java8 流? (拉)
使用 java.util.Stream
这很容易:Service
创建一个 Stream
,它在后台使用数据库游标。每次 Jackson
为 Stream
的一个元素写入 JSON 字符串时,它会请求下一个,然后触发数据库游标到 return 下一个条目。
RxJava/响应式/可观察? (推)
这里我们有相反的情况:数据库必须逐个条目推送并且 Jackson
必须为每个元素创建 JSON 字符串,直到 onComplete
方法被调用.
即Controller
告诉 Service
:给我一个 Observable<Article>
。然后 Jackson
可以请求尽可能多的数据库条目。
分歧与关注:
使用 Streams
在 请求下一个数据库条目和检索/处理它 之间总会有一些延迟。如果网络连接速度慢或必须发出大量数据库请求才能完成响应,这可能会减慢 JSON 响应时间。
使用RxJava
应该总是有数据可供处理。如果太多,我们可以使用背压来减慢从数据库到应用程序的数据传输。在最坏的情况下,buffer/queue 将包含 所有 请求的数据库条目。那么内存消耗将等于我们当前使用 List
.
我为什么要问/我在问什么?
我错过了什么?还有其他优点/缺点吗?
为什么(特别是)Spring 数据团队扩展他们的 API 以支持来自数据库的
Stream
响应,如果总是有(短)延迟每个数据库之间request/response?对于大量请求的条目,这可能会导致一些明显的延迟。对于这种情况,是否建议使用
RxJava
(或其他一些反应性实现)?还是我遗漏了什么缺点?
您似乎在谈论底层数据库引擎的提取大小。
如果将其减少到一个(一次获取和处理一行),是的,您将在请求时间内节省一些 space...
但是拥有合理的块大小通常是有意义的。 如果它太小,你将有很多昂贵的网络往返。如果块大小太大,您将面临 运行 内存不足的风险,或者每次提取都会引入过多的延迟。所以这是一种妥协,正确的 chunk/fetch 大小取决于您的具体用例。
关于反应式与否,我认为这无关紧要。与 RxJava 和 Cassandra 一样,可以从异步结果集创建一个 Observable,这取决于查询(配置)一次应该获取和推送多少项。