技术标签: spring spring boot java 后端 java工具
项目场景:实际项目创建一个固定数量的线程池,用来消费用户数据,但偶尔会发现有些线程消失了,也就是线程不进行工作,实际工作的线程数量一直减少,直至彻底不消费用户数据。
Executor executor = Executors.newFixedThreadPool(100);
首先排除代码的逻辑错误,确保没有出现死锁等情况。在确保没有死锁的情况下,通过Thread Dump得到日志进一步分析。
"pool-6-thread-29" #118 prio=5 os_prio=0 tid=0x00007ff9dc006800 nid=0x6ee0 runnable [0x00007ff9c59e6000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:593)
at sun.security.ssl.InputRecord.read(InputRecord.java:532)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
- locked <0x00000006d298e328> (a java.lang.Object)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
- locked <0x00000006d298e338> (a java.lang.Object)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.upgrade(DefaultHttpClientConnectionOperator.java:193)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.upgrade(PoolingHttpClientConnectionManager.java:389)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:416)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:89)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:724)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:681)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:597)
....
通过任务对应得到“消失的线程”,得到线程的name,拿到线程对应具体状态RUNNABLE。
在java的文档里对RUNNABLE的描述是这样的:
A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
处于 runnable 状态下的线程正在 Java 虚拟机中执行,但它可能正在等待来自于操作系统的其它资源,比如处理器。
根据堆栈信息,可以看到具体出问题的是使用RestTemplate请求的时候出现问题,有可能是一直等待网络资源。
出现问题的RestTemplate由于业务原因,没有使用默认的SimpleClientHttpRequestFactory,而是使用了HttpClient作为RequestFactory,这里拓展一下,RestTemplate可以设置不同的RequestFactory,通过源码查看,内置已经支持如下:
通过源码直接Debugger到java.net.SocketInputStream,会发现加了代理的请求,请求的SocketTimeout为0,这是最直接的原因,导致了线程一直在登录服务端的返回,彻底阻塞,影响后续任务。
但项目实际设置了ConnectTimeout和SocketTimeout,而且在非代理请求情况,这里显示的是设置的SocketTimeout值,但加了代理后,就出现了0,推测是加了代理,HTTPClient内部的一些问题。
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(httpConfig.getConnectTimeout())
.setSocketTimeout(httpConfig.getReadTimeout())
.setProxy(httpConfig.getProxy())
.setRedirectsEnabled(httpConfig.isRedirect()).build();
圈红框部分的代码,就是代理为了创建代理路由需要额外运行的代码,重点在:
case HttpRouteDirector.CONNECT_PROXY:
this.connManager.connect(
managedConn,
route,
timeout > 0 ? timeout : 0,
context);
final HttpHost proxy = route.getProxyHost();
tracker.connectProxy(proxy, false);
break;
其中在创建SocketConfig的过程中,代码如下:
org.apache.http.impl.conn.PoolingHttpClientConnectionManager#resolveSocketConfig
private SocketConfig resolveSocketConfig(final HttpHost host) {
SocketConfig socketConfig = this.configData.getSocketConfig(host);
if (socketConfig == null) {
socketConfig = this.configData.getDefaultSocketConfig();
}
if (socketConfig == null) {
socketConfig = SocketConfig.DEFAULT;
}
return socketConfig;
}
该方法默认中,socketConfig 、this.configData.getDefaultSocketConfig();都为空,所以代理路由Route使用了默认的SocketConfig.DEFAULT。
查看org.apache.http.config.SocketConfig的默认对象:
此处默认的SocketTimeout为0,没有超时,一直阻塞。
到此为止,定位到了具体的错误根源。
根据资料查找
1、httpclient 4.3.6之前的一个bug,会导致连接一直阻塞,导致不会超时,但检查项目httpclient版本高于4.3.6。
2、官方已经提示jdk8的某些版本存在该bug,但新版本已经修复,本次出现问题的jdk版本为1.8.0_25和1.8.0_191,处于未修复的版本,需要自己项目代码进行修复。
[JDK-8075484] SocketInputStream.socketRead0 can hang even with soTimeout set - Java Bug System
https://bugs.openjdk.java.net/browse/JDK-8075484#
private SocketConfig resolveSocketConfig(final HttpHost host) {
SocketConfig socketConfig = this.configData.getSocketConfig(host);
if (socketConfig == null) {
socketConfig = this.configData.getDefaultSocketConfig();
}
if (socketConfig == null) {
socketConfig = SocketConfig.DEFAULT;
}
return socketConfig;
}
从上面的 this.configData.getDefaultSocketConfig();入手,设置DefaultSocketConfig();
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(httpConfig.getConnectTimeout())
.setSocketTimeout(httpConfig.getReadTimeout())
.setProxy(httpConfig.getProxy())
.setRedirectsEnabled(httpConfig.isRedirect()).build();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
getSSLContext(), new String[]{
"TLSv1"}, null,
NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(config).setSSLSocketFactory(sslSocketFactory)
.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
//这里修改默认配置里的的SocketTimeout为40秒
.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(40000).build()).build();
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
重点就是加了一行代码:.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(40000).build())
2.打印1~100之间所有是7的倍数的整数的个数及总和(体会设置计数器的思想)public class Test2{ public static void main(String[] args){ int a=0; int sum=0; for(int i=0;i<=100;i++){ if(i %7==0){ a+=1; sum+=i; } ..._用java编写程序打印1~100之间所有7的倍数的整数的个数及其总和 while
在使用xray或者burpsuite的时候都是要设置本地代理。使用一个代理。若要同时使用xray和burpsuite则需要开启两个浏览器,这样不怎么方便。burpsuite里面有一个插件passive-scan-client.0.1.jar可以把流量转发到其它端口上。_burp suite联动xray
CoreText.framework
电气设备的工作原理及各电器元件相互之间的关系,对于快速掌握设备工作原理、分析电气线路、排除电路故障、程序编写等十分有益。现有基于浮云E绘图SDK(包含电路图编辑器+绘图DLL组件+API Demo+电子元件模板库+说明文档),可以快速绘制开发CAD电路图(电气原理图),并且实时更新图形各元件的状态。 ........._快速定制开发cad电路图(电气原理图)详细流程及源码 浮云e绘图
《看技术博客:关键在于一步一步执行到底,耐心,你一定可以的》一.简单两步:1.下载 2.配置 tips:eclipse为绿色软件(无需配置),只要jdk配置好后 打开eclipse就可使用二. (1)下载:(下面链接针对 64位的系统,32位原理一样) (注意:ctrl+点击
首先使用system登录,他是最高权限的然后创建表空间create tablespace abs_businessdatafile 'D:\OracleDBF\abs_business.DBF'size 100mautoextend on next 10mabs_business为表空间datafile 用于设置物理文件名称,这里存放在D:\OracleDBF中size...
def oct(*args, **kwargs): 功能: 返回一个整数的八进制形式。0o表示八进制>>> oct(10)'0o12'_将整数1000用八进制形式可以使用哪个函数?
填充率、画布、输入解决填充率问题在第一篇中介绍了填充率以及过度绘制,过度绘制会造成GPU片段管线处理压力,主要有两种方式来减少这种压力(片段管线主要是负责像素输出): 1. 减少 shader 片段的复杂度,详细参考下面 “UI Shader和低配设备” 章节内容。 2. 减少需要采样的像素数量。由于内置的UI Shader都是标准通用的,一个很大问题就是填充率过高。这通常是因...
打开网络上的 ZIP 文件需要几步?下载,解压,拿到所有文件。面对一个 ZIP,能不能「边下边播」、「按需下载」?今年 6 月,优酷绘本技术团队开发出新的解压方式——ZIP 流式解压技术,并成功应用在优酷绘本秒开项目中,30M+ 绘本平均加载时长只需 0.91s,加载耗时比传统的解压方式降低了 88.3%,让用户的阅读体验直线提升。本文将介绍 ZIP 流式解压的原理和技术实现路径,希望为大家带来启发,将 ZIP 流式解压技术更多的应用到业务中。一 什么是ZIPZIP 是一种文件格式,定义了如何将多个
像那些有着深厚的编程公里的程序员们,差不多一两周就能捋清楚Python的学问,而对于那些新手码农们,尤其是0基础的宝宝,可能需要几个月的时间去研究Python。当然,学成之后的收入也是十分可观的。但是,不管你是出于好奇Python语言还是想要转行从事Python这个行业,面对网络上杂七杂八的资料,就是连有经验的程序员一不留神也会掉进坑里。可以说,学习Python如果没有章法,那么编程就无法建立体系,这就导致了一种现象:学了好长的一段时间感觉仍然只学了一个皮毛。在此,小编给大家整理了Python课程大纲
初识访达入手Mac的朋友,访达的功能就相当于是Windows的“此电脑”,访达的初识页面如下:现在我们来说说如何全面的认识访达。一般对于刚入手的Mac的朋友,可能习惯于Windows的操作系统,会使用鼠标去完成需要打开的软件,但是Mac准备了很多快捷简单的快捷键,目的就是让你完全脱离鼠标的控制,快捷键(command+shift+A)可以快速得到以上界面,进行你想要的操作。个人收藏..._mac访达是什么
1 UML类图(转自:http://blog.csdn.net/tianhai110/article/details/6339565)在UML类图中,常见的有以下几种关系:泛化(Generalization)实现(Realization)关联(Association)聚合(Aggregation)组合(Composition)依赖(Dependency)1.1 泛化(Generaliz_coad法则