业务推动实践-浅谈ThreadPoolExecutor

临睡觉的时候,最近在学习spring,学的比较长,想着抽个空隙,边学边记,顺便把最近碰到的问题解决思路也记下来. 事实证明-睡觉前不能乱想.
既然睡不着,就记录一下把.

最近碰到了一个业务需求,定时从外网ES推送一批千万级企业数据到内网ES.

1.

既然是一种大数据量的处理,那必然离不开线程池了.

  new ThreadPoolExecutor(int corePoolSize,// 核心线程数量
                              int maximumPoolSize,// 最大线程数量
                              long keepAliveTime,// 空闲回收时间
                              TimeUnit unit,// 时间单位
                              BlockingQueue<Runnable> workQueue);// 任务队列

1.1

解释线程池之前 我觉得需要知道一下 new Thead()到底做了什么 系统开销了什么
1.11 调用本地naive方法
1.12 调用JVM的C创建线程方法
1.13 再调用OS 也就是操作系统线程 man(pThread)
1.14 OS端创建了线程之后需要和第二步创建的线程进行绑定
1.15 JAVA_START JNI反射调用run方法

线程执行方法时候,会去抢占CPU时间片,运行完 就会释放时间片,所以线程池执行单个任务完成后 会调用一个钩子方法 从任务队列拿下一个任务 控制不释放时间片,这也就是线程复用

1.2

目前为止,用到最多的两种创建方式就是固定线程池和缓存线程池.
固定线程池 核心数量与最大数量相同 第三个参数 相当是一个失效的
缓存线程池:核心数量为0 最大数量大于0
相比之下 固定线程池不用回收线程 而 缓存队列却要重复回收 在偶尔处理数据时候不仅开销大 等待创建Thread再执行run逻辑 反而没一个方法执行的快
就像JVM调优一样 堆举例,其中一个调优方式 就是-Xms和-Xmx设置一样大,官话叫防止内存抖动,个人理解就是防止总是回收内存 再申请扩建内存.

好了,铺垫完成.具体业务,使用线程池,分为两种情况.
CPU密集型 // 业务逻辑计算占大比例
IO密集型 // 业务逻辑中 http请求IO占大比例
我的业务逻辑,很明显是IO密集型,那么创建出一个new ThreadPoolExecutor(2*CPU, 2*CPU, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(“企业数量”))
(这里补充一下 为什么选了LinkedBlockingQueue 而没选ArrayBlockingQueue
虽然它俩的区别很多,但是个人觉得有一个很重要点,LinkedBlockingQueue 入队和出队各有一把锁 而ArrayBlockingQueue只有一把锁 入队或者出队时候 会互斥)

言归正传,线程池创建完成,scroll扫企业名称入队工作.检查一下逻辑没问题,上线.先试一下100个企业把,试了一下 基本点击时候就瞬间完成了.嗯,不错,开始全量工作把.但是发现每秒才完成了几个,不对啊,难道是因为队列任务太大,积压造成的?开始改造代码,创了五个线程池,分配着加进去.部署测试,改观并不大.突然想起来之前压测时候,改过服务器的ip_local_port_range端口最大分配数,
[linux端口分配 程序会选择这个范围内的端口来连接到目的端口 四位标识 本地IP 本地端口 远程IP 远程端口]
最大数量改到65535.再试,还是不行,现在CPU利用率应该一定是够了,判断应该还是http连接数量某个地方出现了限制,是时候呼叫运维了,”ulimit这个会限制“
(进程所占用的资源,最大打开文件数量)

做了修改后改进还是不大, 这时候旁边同事问了我一下 用的什么类发的请求,这才发现用的是因为HttpClient的maxConPerHostmaxTotalCon两个参数的问题.
(maxConPerHost 某一个服务每次能并行接收的请求数量
maxTotalCon 其一次最多接收MaxTotal次请求)

知道了这两个参数含义,都给上65535
重新打包,部署,测试 效率一下就上来了 每秒可以处理完30多个企业.优化告一段落(当然优化首先从代码开始 省份代码 行业代码可以先一次性查出来缓存起来 查询可以多个一起查)

总结一下,
线程池处理业务时候,个人觉得CPU密集型注意事项不会很多,但是IO密集型就需要注意一下相关的系统参数,(线程池中线程数量,httpClient最大接受数量,os端tcp端口分配数量,ulimit最大打开数量)这四个参数 就像四个东西组成了一个水桶 有一个地方细了水流就细了.

猜你喜欢

转载自blog.csdn.net/weixin_45657738/article/details/109153515