GCP PubSub Java订阅者客户端的并发设置



在Java GCP PubSub消费者中有两个重要的字段用于控制并发级别:

  • 平行拉数
  • 执行线程数

来自官方示例:

setParallelPullCount决定订阅者将打开多少StreamingPull流来接收消息。默认为1。setExecutorProvider为订阅者配置一个执行器来处理消息。这里,订阅者被配置为打开2个流来接收消息,每个流创建一个带有4个线程的新执行器来帮助处理消息回调。总共有2x4=8个线程用于消息处理。

所以并行拉计数,如果我没弄错的话,直接指的是Java执行器的数量(=线程池),而执行器线程的数量设置了每个线程池的线程数量。

通常我认为单独的线程池有不同的用例或职责,所以我们可能有一个无界的缓存线程池用于IO,一个固定的线程池用于cpu绑定的操作,一个单一的(或低数量的)线程池用于异步IO通知,等等。

但是,使用两个或多个具有相同属性的线程池来消费和处理pubsub消息,与简单地使用单个线程池并拥有所需的最大线程数相比,有什么好处呢?例如,如果我可以在订阅者上总共预留8个线程,那么使用1x8 vs 2x4组合的具体原因是什么?(8线程的单个池,与拉计数=2使用每个4线程)?

setParallelPullCount选项不只是指JavaExecutors的数量,它指创建的从服务器请求消息的流的数量。由于各种因素,不同的流可能返回不同数量的消息。为了在单个客户端中处理比在单个流(10MB/s)上传输更多的消息,可能需要增加并行拉取计数。这与是否共享执行器/线程池无关。

是否在流之间共享线程池将通过调用setExecutorProvider来处理。如果您设置一个ExecutorProvider,在每次调用getExecutor时返回相同的Executor,那么流将共享它。如果您让它为每个调用返回一个新的Executor,那么它们每个都有自己专用的Executor。默认的ExecutorProvider执行后者。

如果调用setParallelPullCount(X),则setExecutor被调用X次以获得每个流的Executor。在大多数情况下,是所有人共享一个还是每个人单独使用一个可能不会有太大的变化。如果您试图保持总体线程数相对较低,那么共享单个Executor可能会有所帮助。

在带有Y个线程的X个Executors和带有X*Y个线程的一个Executor之间的选择实际上归结为共享这些资源的能力,如果来自每个流的数据量有很大的不同,这可能不是大多数情况下的情况。如果是,那么共享的Executor意味着一个特别饱和的流可以"借用"。不饱和的线。另一方面,使用单独的Executor可能意味着在这种情况下,消息较少的流上的消息与饱和流上的消息一样能够通过。

最新更新