Category: zuul

Scenario

spring-cloud/spring-boot application is using zuul API gateway to route client requests. Here is zuul config snippet

zuul.ribbonIsolationStrategy=THREAD
zuul.threadPool.useSeparateThreadPools=true

ribbon.eureka.enabled = false

# sevices
...

Invoking service APIs through zuul gateway resulted in HTTP 500 response that looked something like this:

{
  "timestamp": "2019-12-18T21:37:10.168+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "REJECTED_THREAD_EXECUTION"
}

Interesting part of this response is REJECTED_THREAD_EXECUTION. None of the services were reporting this message. After looking deeper, the Zuul log showed this error

Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@3b17817e rejected from java.util.concurrent.ThreadPoolExecutor@67f89c35[Running, pool size = 10, active threads = 10, queued tasks = 0, completed tasks = 2535368]
    at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063) ~[?:1.8.0_212]
    at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830) ~[?:1.8.0_212]

Solution

After realizing that exception is in the zuul log it was a matter of finding the right properties to configure services thread pools. By default, zuul was using 10 threads with the max thread count set to 10. To change this default across all services set these properties:

# defualt threadpool config
hystrix.threadpool.default.coreSize = 150
hystrix.threadpool.default.maximumSize = 150

It is also possible to configure thread pools for each service that zuul is routing to. For example:

zuul.routes.first.url=firstServiceId
zuul.routes.second.url=secondServiceId

hystrix.threadpool.firstServiceId.coreSize = 150
hystrix.threadpool.firstServiceId.maximumSize = 150

hystrix.threadpool.secondServiceId.coreSize = 50
hystrix.threadpool.secondServiceId.maximumSize = 150