网站首页 > 教程文章 正文
1.问题
最近接到用户报障,线上某个接口频频超时,故拎出代码,大致如下
list.parallelStream().map(c -> {c.httpGet()}
上面的代码大致意思是并行流循环list,然后去调用一个第三方接口,用这种做法来达到多线程的方式调用第三方接口。
首先承认的是这种写法的人只是想实现某个功能,而没有真实的高并发编程经验和toC经验。
博主回想以前在某互联网公司对于此类接口,统称为“重服务”。如何优化这种场景本篇不提,只是想看看为什么接口会超时。
2.分析过程
分析:
1.查看调用链
查看调用链发现调用链显示串行循环调用三方接口100多次,每次大概500ms所以统计下大概50几秒,而ng侧会在调用超过30ms切掉本次调用
当时心里一想这不是java8的并行流吗,为什么串行循环调用。而不是并行去调用。一度怀疑调用链出现问题,当然万万不可怀疑是jdk问题。
2.分析源码
java8的流是如上面图结构,最后走的公共线程池是ForkJoinPool,而这个ForkJoinPool的初始化线程池数量为:
再深入到这个方法 ForkJoinPool makeCommonPool() {}
return new ForkJoinPool(parallelism, (ForkJoinPool.ForkJoinWorkerThreadFactory)factory, handler, 0, "ForkJoinPool.commonPool-worker-");
通过上图可以看到:
Runtime.getRuntime().availableProcessors() - 1 如果大于0那么就是这个数,否则 parallelism为1
3.查看日志:
截图当时未保存确实显示的是如下一个线程,验证猜想
ForkJoinPool.commonPool-worker-0
4.进一步验证
线上打印Runtime.getRuntime().availableProcessors()
4.解决
1.临时解决方案
增加jvm参数-Djava.util.concurrent.ForkJoinPool.common.parallelism=10,为parallelStream增加自定义线程池线程数量,这个是全局的慎用
2. 定义自定义的线程池,来代替java8默认线程池
5.为什么Runtime.getRuntime().availableProcessors() =1
需要指明的是本项目是在docker容器里部署
jdk <1.8.0_131 在docker内 获取的是宿主机上的内核数
jdk >=1.8.0_131 在docker内 获取的是docker被限制的内核数
以下2篇文章可以很好的解答这个问题
https://blog.csdn.net/weixin_30905133/article/details/98007814
https://blogs.oracle.com/java/post/java-se-support-for-docker-cpu-and-memory-limits
猜你喜欢
- 2024-12-11 Docker核心:深入理解Dockerfile
- 2024-12-11 教你测试开发丨测试小白也能听懂的Docker讲解和应用
- 2024-12-11 使用dockerfile部署springboot应用
- 2024-12-11 java 打包并上传到hub.docker.com上
- 2024-12-11 使用 Docker 部署 Spring Boot 项目,带劲
- 2024-12-11 全面升级!一套基于Spring Boot 3+JDK17的实战项目!
- 2024-12-11 银河麒麟V10 arm架构docker制作Dragonwell jdk镜像
- 2024-12-11 一文详解 Jenkins 与 Docker 的自动化 CI/CD 实战
- 2024-12-11 docker安装jenkins并且通过jenkins部署项目
- 2024-12-11 Docker 基础与实战,看这一篇就够了
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- md5 sha1 (32)
- mybatis plus page (35)
- semaphore 使用详解 (32)
- update from 语句 (32)
- vue @scroll (38)
- 堆栈区别 (33)
- 在线子域名爆破 (32)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)