springcloud 在Hystrix中出现拒绝服务的熔断异常
·
java.util.concurrent.RejectedExecutionException: Task
java.util.concurrent.FutureTask@3f54147b rejected from
java.util.concurrent.ThreadPoolExecutor@55407c43[Running, pool size = 10, active threads = 10, queued tasks = 0, completed tasks = 2638]
根据文档资料得到,在默认设置下,maxQueueSize的长度为-1,则使用了SynchronousQueue
* maxQueueSize BlockingQueue的最大队列大小,设为-1使用SynchronousQueue,否则使用LinkedBlockingQueue,默认值:-1
翻hystrix线程池的代码,得到如果是-1的情况下,hystrix是不进行判断队列的长度的,此时,直接交由线程池去处理。
//HystrixThreadPool.java
@Override
public boolean isQueueSpaceAvailable() {
if (queueSize <= 0) {
// we don't have a queue so we won't look for space but instead
// let the thread-pool reject or not
return true;
} else {
return threadPool.getQueue().size() < properties.queueSizeRejectionThreshold().get();
}
}
通过异常,我们得知,产生的原因是因为队列无法加入任务被reject了,当我们设置-1的时候,此时的队列用的实现是SynchronousQueue(0),意味着,线程池不会进行等待,如果对应的任务满了coreSize,则直接被默认的策略reject掉。
(hystrix使用的拒绝策略是满了直接拒绝)
//HystrixConcurrencyStrategy.java
/**
* Factory method to provide instance of {@code BlockingQueue<Runnable>} used for each {@link ThreadPoolExecutor} as constructed in {@link #getThreadPool}.
* <p>
* Note: The maxQueueSize value is provided so any type of queue can be used but typically an implementation such as {@link SynchronousQueue} without a queue (just a handoff) is preferred as
* queueing is an anti-pattern to be purposefully avoided for latency tolerance reasons.
* <p>
* <b>Default Implementation</b>
* <p>
* Implementation returns {@link SynchronousQueue} when maxQueueSize <= 0 or {@link LinkedBlockingQueue} when maxQueueSize > 0.
*
* @param maxQueueSize
* The max size of the queue requested via properties (or system default if no properties set).
* @return instance of {@code BlockingQueue<Runnable>}
*/
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
/*
* We are using SynchronousQueue if maxQueueSize <= 0 (meaning a queue is not wanted).
* <p>
* SynchronousQueue will do a handoff from calling thread to worker thread and not allow queuing which is what we want.
* <p>
* Queuing results in added latency and would only occur when the thread-pool is full at which point there are latency issues
* and rejecting is the preferred solution.
*/
if (maxQueueSize <= 0) {
return new SynchronousQueue<Runnable>();
} else {
return new LinkedBlockingQueue<Runnable>(maxQueueSize);
}
}
通过上述,解决这个异常的问题通过两条路,一个是修改线程池的等待队列,一个是加大工作线程数(不建议改coreSize,应该通过修改最大线程数来变更,避免有常驻线程过多)。
1、同时设置
1、同时设置队列长度跟拒绝长度
maxQueueSize: 1000 #BlockingQueue的最大队列数,默认值-1
queueSizeRejectionThreshold: 800 #即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝,默认值5
2、同时设置最多工作线程数以及allowMaximumSizeToDivergeFromCoreSize
maximumSize: 100
allowMaximumSizeToDivergeFromCoreSize: true
更多推荐


所有评论(0)