一、接口级别通用属性配置
1、validation配置
优先级:consumer>provider,两端都手动配置的情况下,如果验证不通过,只有客户端会报错
配置建议:provider端validation 配置为false,consumer端配置为true(默认是false)
2、timeout配置
优先级:方法>接口>全局 consumer>provider
配置建议:consumer配置的大于provider配置的,具体根据业务定
3、retries配置
优先级:consumer>provider,
配置建议:为避免provider不可控,重试次数由provider端设置,consumer端禁止配置(默认的2会被provider配置的覆盖),写请求通常为0,读请求可走默认值
二、consumer端
1、check配置(consumer端)
配置建议:默认为true,走默认值即可
2、actives 每服务消费者每服务每方法最大并发调用数
配置建议:默认0即可,如果大于零会限制引用方法级别的并发调用数(就是消费端的请求发不出去 源码:ActiveLimitFilter)
3、connections(consumer端)
所有接口共享长连接,只负责网络传输,性能瓶颈不会出现在这里
配置建议:0 或者不配置
三、provider端
1、delay(provider端)
配置建议:没有特殊如缓存等需要配置的话 走默认(为null) 或设置为-1即可,spring初始化完毕之后会注册到zk
2、accepts(provider端)
控制netty的channel数量
配置建议:0或不配置,(如果大于0,必须大于等于consumer端数量*connections数量)
3、iosthreads
负责io数据读写
配置建议:默认值(cpu数量+1)
4、threads(provider-protocol)
实际业务处理线程池,配合queue使用
配置建议:根据实际业务调整,建议queue=默认值0,防止业务堆积
5、executes(provider)
类似consumer端的actives
配置建议:默认0即可,如果大于零会限制方法级别的并发请求数(就是provider端的收到请求大于配置的值后立刻报错 源码:ExecuteLimitFilter)
流程说明:
1、当consumer发起一个请求时,首先经过参数actives进行方法级别的限制,
收到请求时通过private final AtomicInteger active = new AtomicInteger();加1,请求完成(包括异常)减1,如果超过actives则调用wait等待其他请求完成后重试或者超时后失败;【ActiveLimitFilter】
2、从consumer和provider之间建立的长连接通道发送业务参数到provider端(如果进行了配置accepts必须大于等于consumer端数量*connections数量)
3、收到请求通过iothread读取内容【参考netty的多线程模型】
4、反序列化后交由业务线程池处理
5、executes是提供端生产级别的并发控制,大于executes立刻报错,类似于actives,一个是多的请求发不出去,一个是多的请求不接。【ExecuteLimitFilter】
总结:
1、核心的逻辑瓶颈是在provider端的threads数和consumer端的actives数乘以consumer端数量大小,如果后者大太多,重试也大概率会失败。
2、个别方法性能有问题可单独调整executes
3、整体性能有问题,可尝试调threads