Spring Webflux线程使用情况调研

Stack overflow: Threading model of Spring WebFlux and Reactor
Netty reactor thread modeling
Spring framework reference: webflux-concurrency-model

Spring MVC vs Spring WebFlux

  • Architecture diagram


    Spring Webflux线程使用情况调研_第1张图片
    image.png
Spring Webflux线程使用情况调研_第2张图片
image.png

Threading Model

  • For WebFlux Http request handling

    • On a "vanilla" Spring WebFlux server (e.g. no data access, nor other optional dependencies), you can expect one thread for the server, and several others for request processing (typically as many as the number of CPU cores). Servlet containers, however, may start with more threads (e.g. 10 on Tomcat), in support of both servlet, blocking I/O and servlet 3.1, non-blocking I/O usage.
    • The reactive WebClient operates in event loop style. So you’ll see a small, fixed number of processing threads related to that, e.g. "reactor-http-nio-" with the Reactor Netty connector. However if Reactor Netty is used for both client and server, the two will share event loop resources by default.
    • Reactor and RxJava provide thread pool abstractions, called Schedulers, to use with the publishOn operator that is used to switch processing to a different thread pool. The schedulers have names that suggest a specific concurrency strategy, e.g. "parallel" for CPU-bound work with a limited number of threads, or "elastic" for I/O-bound work with a large number of threads. If you see such threads it means some code is using a specific thread pool Scheduler strategy.
    • Data access libraries and other 3rd party dependencies may also create and use threads of their own.
  • For MongoDB

    • DB access and subsequent data operation via thread created from NioEventLoopGroup.
    • NioEventLoopGroup is created by MongoReactiveAutoConfiguration and can be configured via MongoClientSettings
    • Thread number is defined in MultithreadEventLoopGroup: DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2))

Thread usage records in our server

Local Macbook pro 2015 15 inch', with 4 cores and 8 threads

Thread used in single call
  • Main - Application startup
  • reactor-http-nio-x - Request handler & Response Handler for both Http and Websocket
  • nioEventLoopGroup-2-y - Reactive mongo repository
Thread used in concurrent calls from 100 users

Using Gatling to make 100 concurrent calls on the Http apis:

  • /lexicons
  • /lexicons/random
  • /users

Using Gatling to make 20 concurrent calls on the Websocket apis:

  • /join then send Command(REFRESH)

Thread used (Http and websocket have the same result):

  • reactor-http-nio-x: 8 threads
  • nioEventLoopGroup-x-y: 16 threads

Issue records

  • LexiconRepositoryCustom should be implemented in a non-blocking way. Which means the syncronized data CURD with mongoTemplate should be deffered and dispatched to another thread. (Which thread pool?)
    Solution: Replace MongoTemplate with ReactiveMongoTempate
  • All service executions are running on nioEventLoopGroup-x-y because they start with repository calls. Should we dispatch it back to ctor-http-nio-x?
    Answer: No need. As long as it dose no block the nio threads.

你可能感兴趣的:(Spring Webflux线程使用情况调研)