Dubbo线程数量到底设置多少合适?

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

我们的基础服务RPC日调用量已经到2千万以上,设置线程数时也需要注意,做一些基本的估算

影响线程池数量因素:

1. 在 不考虑系统本身限制 的情况下,主要跟JVM一下几点有关:

  • -Xms 初始堆大小 (在实际生产中,一般把-Xms和-Xmx设置成一样的。)
  • -Xmx 最大堆大小
  • -Xss 每个线程栈大小

1): 当给JVM的堆内存分配的越大,系统可创建的线程数量就越少(可以通过上面测试程序,不断的改变-Xmx,-Xms的值,观看最后异常时的线程数量)。这个如何理解呢?很简单,因为线程占用的是系统空间,所以当JVM的堆内存越大,系统本身的内存就越少,自然可生成的线程数量就越少。
2): 当-Xss的的值越小,可生成的线程数量就越多。*(一样可以通过上面测试,保持-Xmx,-Xms不变,改变-Xss的值,jdk5以下默认好像是256K,以上默认为1M,具体记不太清楚了)。这个理解也很简单,线程可用空间保持不变,每个线程占用的栈内存大小变小,自然可生成的线程数量就越多。

2. 系统层面影响

那么是不是不断加大可用内存,线程数量也会不断增长呢?
这个当然不是,上面我特意加粗了不考虑系统本省限制的情况,所以说线程数量还与系统限制有关。主要跟一下几个参数有关(Linux下的):

  • /proc/sys/kernel/pid_max 增大,线程数量增大,pid_max有最高值,超过之后不再改变,而且32,64位也不一样
  • /proc/sys/kernel/threads-max 系统可以生成最大线程数量
  • max_user_process(ulimit -u)centos系统上才有,没有具体研究
  • /proc/sys/vm/max_map_count 增大,数量增多

总结 :  JVM线程最大数量由JVM的堆(-Xmx,-Xms)大小、Thread的栈(-Xss)内存大小、 系统最大可创建的线程数的限制参数三个方面影响。
不考虑系统限制,可以通过这个公式估算:

线程数量 = (机器本身可用内存 - (JVM分配的堆内存+JVM元数据区)) / Xss的值。

Dubbo线程池配置:

主要线程配置在 protocol 配置项中 详细见官方文档:thread-model,

  • threadpool 线程池类型,可选:fixed, cached, limited, eager, 一般配置 cached就OK
  • threads 服务最大线程池,根据上面的计算,来适当配置
  • iothreads cpu个数+1 io线程池大小(固定大小) ,不可优化
  • accepts 服务提供方最大可接受连接数,默认0

单个 service 线程配置,一般不需要单独配置,除非是高频服务

  • threads 服务线程池大小
  • executes:一个服务提供者并行执行请求上限,即当 Provider 对一个服务的并发调用达到上限后,新调用会阻塞,此时 Consumer 可能会超时。在方法上配置dubbo:method则针对该方法进行并发限制,在接口上配 置dubbo:service,则针对该服务进行并发限制

线程池调整思路:

1.  根据机器内存调整线程数,根据系统配置,优化linux 线程核io相关limit,根据linux系统可用线程数,适当调整线程数上限;

以单个服务为例:  服务器配置:8c32g  问题:日调用量 2千万,1小时内调用量最高的时候 2百万,配置线程数500,不够用了,调整思路如下:

  • <1> 根据给jvm分配的内存 调整 线程数,7个服务JVM堆分配的总内存 17G左右 + JVM元数据区内存(2G), 剩余13G -> 13G/1M(线程栈大小)约等于 1.3万,在去除tomcat和系统本身线程数,理论Java线程数上限可以达到(所有) 1w左右,单个服务调整可以按照1.5倍或者两倍进行增加调整, 那么园务服务的线程数可以调整到 800或者1000
  • <2> 调整linux 用户上限线程数

2. Dispatcher 改为: message,或者connection

  • message: 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。
  • connection: 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。

Jvm到底能创建多少个线程?

我们可以通过下面的代码来做一些测试看看JVM到底能创建多少线程

public class TestThread {
    private static Object lockObj = new Object();
    private static int count = 0;
    public static void main(String[] args){
        for(;;){
            new Thread(new Runnable(){
                public void run(){
                    synchronized(lockObj){
                        count += 1;
                        System.out.println("Thread #"+count);
                    }
                    for(;;){
                        try {
                            Thread.sleep(1000);
                        } catch (Exception e){
                            System.err.println(e);
                        }
                    }
                }
            }).start();
        }
    }
}

主要关注和调整几个参数: JVM最大 堆内存,线程栈大小和本机内存;

  1. 先设置一个较大的JVM堆内存,默认线程栈大小,进行测试
  2. 和1一样的JVM堆内存,调小java线程栈大小 如: 64k, 进行测试
  3. 设置一个比较小的堆内存,默认线程栈大小,进行测试
  4. 和3一样的JVM堆内存,调小java线程栈大小,进行测试

 

Dubbo线程数量到底设置多少合适?_第1张图片

 

转载于:https://my.oschina.net/whxia320/blog/3030167

你可能感兴趣的:(Dubbo线程数量到底设置多少合适?)