dubbo异常分析elapsed: 3000, timeout: 3000. concurrent invokes: 20. max concurrent invoke limit: 20

文章讨论了在新环境中部署账单查询服务时遇到的并发调用超时问题,源于Dubbo的ActiveLimitFilter限制了最大并发。问题在于公司的定时任务组件默认配置导致并发过多。解决方法包括移除定时任务或调整服务提供者的actives配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

最近开发一个新环境的多账单查询需求,部署测试环境之后,偶尔出现账单查询失败,查询日志,如下:
在这里插入图片描述
解释:当前服务调用超时,且达到最大并发调用限制

思考:

最大并发调用限制20是很容易达到的,使用的是同一套服务代码,为何其他环境没有出现这个问题呢?为何线上也没有出现这个问题呢?猜测应该是新加的配置导致的这个问题

引入:

ActiveLimitFilter
查看ActiveLimitFilter源码,发现这个异常抛出的由来.服务使用dubbo作为rpc框架,dubbo针对消费者端提供了ActiveLimitFilter 类来限制最大并发数量,保障服务提供者的稳定运行。
下面看源码解析

@Activate(group = CONSUMER)
public class ActiveLimitFilter extends ListenableFilter {

    private static final String ACTIVELIMIT_FILTER_START_TIME = "activelimit_filter_start_time";

    public ActiveLimitFilter() {
        super.listener = new ActiveLimitListener();
    }

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    //这个是服务提供者的url对象,保存了很多信息,如:地址,端口,超时时间,最大调用次数等
        URL url = invoker.getUrl();
        //服务方法
        String methodName = invocation.getMethodName();
        //获取此服务此方法所允许的最大并发调用数
        int max = invoker.getUrl().getMethodParameter(methodName, ACTIVES_KEY, 0);
        //rpcStatus
        final RpcStatus rpcStatus = RpcStatus.getStatus(invoker.getUrl(), invocation.getMethodName());
        //如果当前并发调用数大于最大并发限制
        if (!RpcStatus.beginCount(url, methodName, max)) {
            //获取超时时间
            long timeout = invoker.getUrl().getMethodParameter(invocation.getMethodName(), TIMEOUT_KEY, 0);
            long start = System.currentTimeMillis();
            long remain = timeout;
            synchronized (rpcStatus) {
            //当前并发调用数依旧大于最大并发限制
                while (!RpcStatus.beginCount(url, methodName, max)) {
                    try {
                        //加入等待队列
                        rpcStatus.wait(remain);
                    } catch (InterruptedException e) {
                        // ignore
                    }
                    long elapsed = System.currentTimeMillis() - start;
                    remain = timeout - elapsed;
                    //超过超时时间
                    if (remain <= 0) {
                        throw new RpcException(RpcException.LIMIT_EXCEEDED_EXCEPTION,
                                "Waiting concurrent invoke timeout in client-side for service:  " +
                                        invoker.getInterface().getName() + ", method: " + invocation.getMethodName() +
                                        ", elapsed: " + elapsed + ", timeout: " + timeout + ". concurrent invokes: " +
                                        rpcStatus.getActive() + ". max concurrent invoke limit: " + max);
                    }
                }
            }
        }

        invocation.setAttachment(ACTIVELIMIT_FILTER_START_TIME, String.valueOf(System.currentTimeMillis()));

        return invoker.invoke(invocation);
    }
}    

问题来源:

每服务消费者达到每服务每方法最大并发调用数,且等待时间大于配置超时时间。原因是引入的公司定时任务组件默认配置20,导致出现此异常

问题解决

1,去除导致此异常的定时任务组件,不实际,项目需要引入定时任务。
2,给对应服务提供者配置actives,问题解决

@Reference(actives = 50)
private IHelloProviderService iHelloProviderService;

总结:

当当前执行该方法的线程超出了最大限制,那么可以等待一个timeout时间,如果时间过了还是超出了最大限制,那么就抛出异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值