ZuulException REJECTED_SEMAPHORE_EXECUTION 是一个最近在机能测试中常常碰着的异常。查询资料发明是因为zuul默认每个路由直接用信号量做断绝,而且默认值是100,也就是当一个路由请求的信号量高于100那么就拒绝处事了,返回500。
信号量断绝
既然默认值太小,那么就在gateway的设置提高各个路由的信号量再尝试。
routes: linkflow: path: /api1/** serviceId: lf stripPrefix: false semaphore: maxSemaphores: 2000 oauth: path: /api2/** serviceId: lf stripPrefix: false semaphore: maxSemaphores: 1000
两个路由的信号量分隔提高到2000和1000。我们再用gatling测试一下。
setUp(scn.inject(rampUsers(200) over (3 seconds)).protocols(httpConf))
这是我们的模子,3s内启动200个用户,顺序会见5个API。所以会有1000个request。呆板设置只有2核16G,而且是docker化的数据库。所以整体机能不高。
当作果仍然有57个KO,可是比之前1000个Request有900个KO的比例好许多了。
线程断绝
Edgware
版本的spring cloud提供了另一种基于线程池的断绝机制。实现起来也很是简朴,
zuul: ribbon-isolation-strategy: THREAD thread-pool: use-separate-thread-pools: true thread-pool-key-prefix: zuulgw hystrix: threadpool: default: coreSize: 50 maximumSize: 10000 allowMaximumSizeToDivergeFromCoreSize: true maxQueueSize: -1 execution: isolation: thread: timeoutInMilliseconds: 60000
use-separate-thread-pools
的意思是每个路由都有本身的线程池,而不是共享一个。
thread-pool-key-prefix
会指定一个线程池前缀利便调试。
hystrix
的部门主要配置线程池的巨细,这里配置了10000,其实并不是越大越好。线程池越大削峰填谷的结果越显著,也就是时间换空间。系统的整体负载会上升,导致响应时间越来越长,那么当响应时间高出某个限度,其实系统也算是不行用了。后头可以看到数据。
这次没有500的环境了,1000个Request都正常返回了。
较量
从几张图比拟下两种断绝的结果,上图是信号量断绝,下图是线程断绝。
直观上能发明利用线程断绝的漫衍更悦目一些,600ms内的响应会更多一些。
两张图展示的是同一时刻的Request和Response的数量。
先看信号量断绝的场景,Response per second是慢慢晋升的,可是到达一个量级后,gateway开始拒绝处事。揣摩是高出了信号量的限制或是超时?
线程断绝的这张就较量有意思了,劳务派遣管理系统,可以看到Request per second上升的速度要比上面的快,说明系统是试图吸收更多的请求然后分发给线程池。再看在某个时间点Response per second反而开始下降,因为线程不绝的建设耗损了大量的系统资源,响应变慢。之后因为请求少了,负载低落,Response又开始抬升。所以线程池也并非越大越好,需要不绝调试寻找一个均衡点。
小结
线程池提供了比信号量更好的断绝机制,昆山软件开发,而且从实际测试发明高吞吐场景下可以完成更多的请求。可是信号量断绝的开销更小,对付自己就是10ms以内的系统,昆山软件开发,显然信号量更符合。