1、把代码部署到现网后,厂商进行数据推送测试。
发现一个问题,就是EOF问题。
百度后,从问题表现看,是文件流不完整。
但是,为什么文件流会不完整了。
于是,进行了一系列的排查工作。
首先想到的就是,并发量太大,导致,接口响应不过来,服务主动断开请求,导致流损坏。
于是,我把接口里面的MySQL写入逻辑给注释掉,这样,从而提升接口性能
再次测试
发现,还是有EOF问题。
于是,开始排查性能瓶颈
第1步,在报错的时候,打印CPU、内存、磁盘IO速率
但是,发现,这三者都没达到瓶颈,就是IO的写速度还剩67MB/s的速度
第2步,是调整tomcat连接数配置。依然报错
所以,我继续简化接口,把接口改成,最简单流字节数计算
并获取Content Length参数,进行比对。
这样应该不会在发生这个问题了吧
结果,还是存在断流问题
于是,厂商建议他们的demo程序部署到我们的服务器,进行测试。
结果,他们的程序没有断流现象。
显然,是我这边程序问题
但是,我已经是最基本的流字节遍历了。
最后,我想到,是否是springboot版本的bug -----这里,至于我为什么会这么想,我也不知道,就是没确定原因前,习惯性的根据经验猜测吧。
于是,我把 2.1.13.RELEASE 版本,换成 2.7.2版本,这个断流问题,没有了。
但是,后来发现也不是这个原因。
因为,我重新整理了一个工程,springboot版本用的就是 2.1.13.RELEASE 版本 ----这里为什么做这个测试,出于就是职业习惯,用控制变量法查找原因。
也没有出现断流问题
最后判定,应该是原工程包做的什么切面配置,导致每个请求前后都要处理一下逻辑
但是,这个无法验证,因为,我本地用同样的文件进行提交,并没有出现问题。
所以,一直没找到问题的原因。
最终,因为客户要求,需要https协议报送数据,于是我整合了https协议功能,出现了断流问题。 ---确定了断流原因
整理了新的工程包后,出现另外一个问题,厂家对接时,偶尔收不到body里面的json
我经过多番测试,没有问题。
后来厂家自己修改了读取body内容的方式,问题得以解决。
最终实现效果:
1900份数据,2000多次请求,每次50条左右,1分钟内刷完
估算一天可以刷1.4亿数据。
tomcat线程配置:
server:
port: 8080
tomcat:
## 等待队列长度,默认100。
accept-count: 65535
## 最大可被连接数,默认10000
max-connections: 65535
## 最大工作线程数,默认200。(4核8g内存,线程数经验值800,操作系统做线程之间的切换调度是有系统开销的,所以不是越多越好。)
max-threads: 2000
## 最小工作空闲线程数,默认10。
min-spare-threads: 500
以上整个过程,大概持续了1周时间,搞的我几天没睡好觉。
工具类(只能在Linux环境使用):
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class SystemMonitor {
public static String getSystemParams(){
final long GB = 1024 * 1024 * 1024;
OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
String osJson = JSON.toJSONString(operatingSystemMXBean);
// System.out.println("osJson is " + osJson);
JSONObject jsonObject = JSON.parseObject(osJson);
double processCpuLoad = jsonObject.getDouble("processCpuLoad") * 100;
double systemCpuLoad = jsonObject.getDouble("systemCpuLoad") * 100;
Long totalPhysicalMemorySize = jsonObject.getLong("totalPhysicalMemorySize");
Long freePhysicalMemorySize = jsonObject.getLong("freePhysicalMemorySize");
double totalMemory = 1.0 * totalPhysicalMemorySize / GB;
double freeMemory = 1.0 * freePhysicalMemorySize / GB;
double memoryUseRatio = 1.0 * (totalPhysicalMemorySize - freePhysicalMemorySize) / totalPhysicalMemorySize * 100;
Runtime run = Runtime.getRuntime();
long max = run.maxMemory();
long total = run.totalMemory();
long free = run.freeMemory();
long usable = max - total + free;
StringBuilder result = new StringBuilder();
result.append("系统CPU占用率: ")
.append(twoDecimal(systemCpuLoad))
.append("%,系统内存占用率:")
.append(twoDecimal(memoryUseRatio))
.append("%,系统系统总内存:")
.append(twoDecimal(totalMemory))
.append("GB,系统剩余内存:")
.append(twoDecimal(freeMemory))
.append("GB,该进程占用CPU:")
.append(twoDecimal(processCpuLoad))
.append("%");
StringBuilder jvmResult = new StringBuilder();
jvmResult.append("最大JVM内存 = ").append(max/(1024 * 1024))
.append("MB,已分配的JVM内存 = ").append(total/(1024 * 1024))
.append("MB,剩余JVM内存 = ").append(free/(1024 * 1024))
.append("MB,最大可用JVM内存 = ").append(usable/(1024 * 1024))
.append("MB");
return result.toString() + " \n" + jvmResult.toString();
}
public static double twoDecimal(double doubleValue) {
BigDecimal bigDecimal = new BigDecimal(doubleValue).setScale(2, RoundingMode.HALF_UP);
return bigDecimal.doubleValue();
}
public static String executeNewFlow(List<String> commands) {
Runtime run = Runtime.getRuntime();
String rspLine = "";
StringBuilder builder = new StringBuilder();
try {
Process proc = run.exec("/bin/bash", null, null);
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
for (String line : commands) {
out.println(line);
}
// 这个命令必须执行,否则in流不结束。
out.println("exit");
builder.append("\n");
while ((rspLine = in.readLine()) != null) {
builder.append(rspLine+"\n");
}
proc.waitFor();
in.close();
out.close();
proc.destroy();
} catch (Exception e1) {
e1.printStackTrace();
}
return builder.toString();
}
}