某客户行政门户k3s网络故障案例

1、出现问题 ​ 在我们吃饭的过程中,小伙伴告诉我客户的系统出现问题了,我们赶快吃完饭回去帮忙排查。当我们回去的时候,被告知问题已经被修复了,但是问题根源没有找到。故障原因给出的是: 服务重启后对应服务配置文件丢失。但是我们觉得问题没那么简单,首先是什么配置文件在什么情况下导致的丢失? 2、排查原因 接下来我们带着疑问展开排查。通过沟通我们知道配置丢失的服务为:app-gateway。我们先看看他们现在是什么样子的配置,如图1所示: 图1 通过这里我们看到此服务里面配置了环境变量NACOS_HOST和NACOS_PORT,这里配置的是一个固定的IP,这个IP是什么的值?通过命令进行查看,我们发现这个值是app-register的pod IP,结果如图2所示: 图2 根据环境变量的名称,我们可以知道这个服务其实就是NACOS服务,NACOS服务就是配置中心,服务在启动的过程中,会去到NACOS服务中获取配置项,pod IP是一个易变的值,很容易就发生变化了。他们这里出现问题,是不是因为pod IP改变,导致服务在启动的过程中找不到配置中心,导致出现的问题呢?我们对比了app-gateway的k8s rs的变更前后的版本,发现之前根本就没有NACOS配置相关环境变量,这个是他们后面手动加上去的。结果如图3所示: 图3 后面根据沟通,才知道他们指的配置丢失,就是他们找不到是在哪里配置去连接NACOS的地址和端口,所以他们才在deployment中手动进行了配置。沟通结果如图4: 图4 这个时候我们怀疑是通过Dockerfile的ENV指令进行的配置,但是开发贴出了Dockerfile的相关配置,如图5所示: 图5 这里的Dockerfile很干净利落,确实是没有我们要的NACOS相关的ENV配置,这个时候我怀疑是不是配置在xxxx/java:1.8-full这个基础镜像里面呢?因为这个基础镜像看起来不像是官方的JDK镜像。我们要求开发提供了此镜像,在我们的服务器上面通过导入镜像,并查看环境变量,也没有发现相关环境变量。 # docker run --rm -it xxxx/java:1.8-full ash /usr/lib/java # env HOSTNAME=cf3ae10caa94 SHLVL=1 HOME=/root TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/java/jdk1.8.0_202/bin LANG=C.UTF-8 TIME_ZONE=Asia/Shanghai CLASSPATH=.:/usr/lib/java/jdk1.8.0_202/lib/dt.jar:/usr/lib/java/jdk1.8.0_202/lib/tools.jar JAVA_HOME=/usr/lib/java/jdk1.8.0_202 PWD=/usr/lib/java 这就很奇怪了,肯定有一个地方要配置NACOS的地址,根据开发的说法是:不在代码里面,那就应该是环境变量或者configmap、secret之类的里面,不然应用不可能知道NACOS在哪里。我们已经看过了,app-gateway的deployment里面是没有配置configmap或secret的,那就应该是环境变量里面。结果环境变量里面也没有。那真相只有一个:NACOS的地址就是配置在代码里面的。 2、查看代码配置 代码是使用Java写的,这里简单说一下:Java的jar包其实就是zip包,我们可以把jar包拿下来通过unzip解压缩,然后使用grep进行搜索,看看代码里面是否有NACOS相关配置项。搜索结果如下: # egrep -r -i 'nacos' * BOOT-INF/classes/logback-spring.xml: <!--nacos 心跳 INFO 屏蔽--> BOOT-INF/classes/logback-spring.xml: <logger name="com.alibaba.nacos" level="OFF"> BOOT-INF/classes/bootstrap.yml: nacos: BOOT-INF/classes/bootstrap.yml: server-addr: ${NACOS_HOST:app-register}:${NACOS_PORT:8848} 我们可以看到代码里面:BOOT-INF/classes/bootstrap.yml 这个文件里面配置的有NACOS相关路径。我们可以看一下这个文件里面都有什么: server: port: 9999 spring: application: name: app-gateway cloud: nacos: discovery: server-addr: ${NACOS_HOST:app-register}:${NACOS_PORT:8848} config: server-addr: ${spring.cloud.nacos.discovery.server-addr} file-extension: yml shared-configs: - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} profiles: active: dev 这里我们简单的说一下:${NACOS_HOST:app-register} 这个配置语法是:如果存在环境变量NACOS_HOST,那么这里的值就是环境变量:NACOS_HOST的值,如果环境变量NACOS_HOST不存在,这把值配置为:app-register,端口也是一样的,就是如果没有环境变量就去默认的8848,从这里我们可以得出:代码里面已经配置了NACOS的地址和端口,并不是开发所说的没有配置,不配置环境变量其实就是取默认值。我们通过kubectl get svc 输出如图6所示: ...

March 16, 2026

某医院数据上云性能优化

1、前言 ​ 之前小伙伴在做技术分享的时候,分享了他们做的某医院数据上云方案。当时大致了解了一下,他们之所以要做这个主要是因为:客户的数据是存储在共享存储上面的,通过samba协议进行共享读写访问。这个数据还要上传到云上进行读取,因为有部分用户需要从公网拉取此数据,再加上IDC机房的存储设备总归是有其存储量上限的,按照国家规定,相关数据也要保留一定的年限。所以 必须要进行数据上云备份和访问。由于使用的是samba协议,我们平常所使用的inotify+rsync的方式是无法实现的。他们之前使用过直接采用rsync进行全量数据推送,但是由于数据量太大了,推送一次就需要12个小时左右,这期间新增的文件可能会被遗漏,就是说最大可能存在12个小时的数据延迟。这显然是无法接受的,他们后续有使用Python、ossutil 都进行了尝试。发现性能都无法满足要求(客户要求半个小时以内),最终选择使用golang进行数据上传,小伙伴当时说使用golang之后,数据延迟在10分钟以内。说实话当时我听到这个时间的时候,觉得还是延迟很大,不过 能满足客户性能要求了,我之前讲过性能优化是无止境的,能满足要求就可以了。当时我也提出可以加大并发吗?小伙伴反馈加大并发会导致应用崩溃。 2、出现问题 ​ 显然事情并没有我们小伙伴讲的那么简单,我后面时不时的会看到医院方反馈数据延迟过大。显然这里面的性能还是存在较大的问题的,实际上并不能满足客户的要求。既然可能存在问题,我们还是仔细的研究一下看是否存在问题。经过了解可知:大致上的架构图如图1所示: 图1 从上图可以看到,架构非常的简单:就是producer和consumer都通过samba挂载存储服务器,producer通过crontab每5分钟去扫描一次samba存储,读取之后跟日志文件中的记录做比对,发现有目录下面的文件数量跟日志文件中记录的不一致,就会把目录发给rabbitmq,然后consumer从MQ中读取目录信息,把此目录进行一次数据同步到OSS。咋一看,没有什么大的问题,通过producer和consumer把数据比对和数据上传进行了解耦。主要的问题是:producer由于是读取的本地日志文件,存在单点问题,并且单点代表着无法随便扩充producer的节点数量。 3、尝试优化 ​ 我们通过了解情况之后,出于运维工程师的习惯。还是希望经过简单的调整,就能达到客户的性能要求。所以 我们没有针对上面发现的问题进行优化。相对上面需要修改源码,我们直接优化samba协议会更简单。既然要优化samba协议,我们要看一下samba挂载的参数是什么样子的,如下所示: //192.168.10.20 on /mnt/source/test type cifs (rw,relatime,cache=struct,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.10.20,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mapposix,rsize=1048576,wsize=1048576,echo_interval=60,actimeo=1) 我们的producer和consumer都是CentOS7,我们查阅了很多资料,有很多资料反馈说:CentOS7在挂载的时候,如果不声明samba的协议版本,那么默认是采用samba 1.0,而samba1.0协议存在很大的性能问题。根据资料,我们尝试把挂载参数加上 vers=3.0,强制让samba协议走3.0 。这里就算是默认挂载的是3.0,我们再显式声明一下也是没问题的。没必要去猜挂载的协议到底是不是3.0,由于数据量比较大,我们没有采取抓包分析,如果抓包分析肯定是可以分析出现到底采用的是哪个版本的协议。我们经过测试:发现修改之后,确实是存在性能提升的。效果如图2所示: 大致上性能提升了1倍左右,左边的是优化前的,右边是优化后的时间。这个结果我们是经过多次测试的,都是同样的。我们很高兴的就把优化参数进行了配置。 4、再次优化 ​ 如果这么简单就完成了优化,那么这个事情是不会成为一个案例的。果然不出所料的再次出现问题。负责客户的小伙伴反馈:优化之后,问题并没有解决,反而更加严重了。对此情况,我们并不慌。出现问题就解决问题,这个本身就是运维工程师的本能。经过排查:我们发现大量的消息堆积在rabbitmq,那么说明consumer存在性能问题?我们跟小伙伴沟通了一下,这个之前是做的consumer并发,每次取20条消息进行消费,然后并发进行消费。消费完之后,rabbitmq会再发送新的消息过来消费的。代码如下(代码有删减): func Consumer(cfgInfo map[string]string) { // 创建RabbitMQ连接 conn, connErr := tools.RabbitMQConn() // 关闭RabbitMQ连接 defer conn.Close() // 获取并发数 concurrentNum, _ := strconv.Atoi(cfgInfo["concurrent"]) for qname, v := range queues { mainWg.Add(1) go func(queueName string) { defer mainWg.Done() // 创建通道 chann, channErr := tools.CreateChann(conn) chann.Qos(concurrentNum, 0, false) // 关闭通道 defer chann.Close() // 创建队列 que, queueErr := tools.CreateQueue(chann, queueName) // 定义一个消费者 msgs, comErr := chann.Consume( que.Name, // queue "", // consumer false, // auto-ack false, // exclusive false, // no-local false, // no-wait nil, // args ) go func() { // 并发消费文件 for d := range msgs { msg := string(d.Body) localfile := v["sourcePath"] + msg alyunfile := v["targetPath"] + msg + "/" ossutilErr := PushDir(localfile, alyunfile) if ossutilErr == nil { consumerLogger.Info("Successfully ossutil sync file: " + msg) consumerLogger.Info(string(out)) } else { consumerLogger.Fatal("Failed ossutil sync file!") } d.Ack(false) } }() // 等待 select {} }(qname) } mainWg.Wait() } 这个咋一看也没有什么大的问题,但是 我们仔细读了一下代码,发现在 最后// 并发消费文件那一行的上面,只使用了一个goroutine来进行执行,而下面是一个for循环,其实简单点说就是:只采用一个协程,按照顺序进行上传操作。就是说实际上并没有并发去消费运行。根据这个我们尝试进行了修复,修复代码如下所示: ...

March 16, 2026

某客户CI/CD再次优化

1、前言 ​ 通过我们的标题就可以看出,我们已经不止一次优化过此流程了,从我们优化之后,一直较为稳定的运行了很长一段时间了,为什么要再次优化呢?其根本原因是由于客户有新的需求了,旧的CI/CD流程在新需求面前确实存在bug。 2、出现问题 ​ 问题出现的很简单:跑CI/CD的过程中,异常退出了,如图1所示: 说实话我刚拿到这个报错的时候,一脸懵逼……报错很简单,执行pushimage的时候,找不到命令。很简单的报错,但是这个流程已经跑了好几年了,几乎是没碰到过这个报错。这个命令其实是通过/tmp/gitci-v3.sh这个脚本source进来的,只要这个脚本存在,不可能会出现没有这个命令的问题。根据上面的截图,可以得出两个疑点:1、可能是在source之前的 ossutil cp 命令存在问题,导致最终此脚本没有执行source操作;2、在执行source的过程中,此脚本的内容发生了变化,可能是空的或者是残缺的,导致最终没有注册pushimage,阿里云年前的重大故障也是类似的,生成的RAM白名单格式是残缺的,又没有校验。导致最终代码在执行的过程中出现故障。 3、尝试伪代码验证修复bug ​ 我们猜测归猜测,还是要考虑客户的实际情况结合起来做判断。客户的新需求其实也简单,在执行CI/CD的过程中,存在大量的同时间并发执行CI/CD。既然是并发执行,跟我们之前的猜测结合起来看:ossutil cp在并发执行的时候,可能存在目标文件被置为空的情况。我在之前接触到这块代码的时候,就怀疑ossutil cp在并发的情况下,可能存在此问题,结果之前并发的量不高,估计是出现的次数太少了。之前应该是开发手动再触发一下就好了。我们根据上下文以及经验判断出了疑点,那就要考虑怎么解决此bug。既然ossutil cp不是并发安全的,我们就再包一层,使用代码达到并发安全的目的。我们计划先ossutil cp到临时文件后mv回gitci-v3.sh脚本来修复此bug,我们首先通过伪代码进行简单的修复验证:通过脚本test-mv.sh进行循环mv替换指定脚本test.sh,然后通过脚本test-source.sh并发source test.sh脚本,测试看生成临时文件后再mv回test.sh脚本,并发source的时候是否正常。 test-mv.sh #!/bin/bash # testing mult mv file and source while true do str=$(openssl rand -hex 4) echo $str testfile=test.sh-$str echo 'function test() {' >> $testfile echo 'echo 'test-$str'' >> $testfile echo '}' >> $testfile sleep 0.1 mv $testfile test.sh done test-source.sh ...

March 16, 2026

某客户ERP 华为云天际助手问题案例

1、客户反馈系统出现502错误 图1 上面的截图,我们大致可以看到浏览器显示的502错误,但是我们还有获知更多的信息。通过沟通我们可以确定:此功能为新上线功能,上线后一直是访问502,但是开发又找不到相关问题,需要我们帮忙定位问题。 2、排查故障原因 我们根据DNS解析找到对应的ELB实例,发现ELB实例没有开启日志记录,我们先根据转发规则查到了后端服务,我们把后端服务的日志打开后进行搜索,发现相对应的时间段并没有日志记录的 502错误。由于日志量比较大,这里就不做展示了。那现在就很有意思了,浏览器上面显示的是:502错误,但是在服务端的日志里面并没有。这是非常奇怪的现象,我们还是建议开启ELB的相关日志,通过ELB的日志再次进行排查。由于日志非常的多,这里有一个测试的小技巧:因为我们测试的系统很多都是有token和cookie进行登录验证的,所以我们可以通过浏览器登录之后,通过F12打开开发控制台,在网络这一栏右键我们要测试的URL,然后选择cURL,这样我们就可以把token和cookie全部复制出来,直接使用CURL进行直接测试,这样更高效,而且可以通过修改http_user_agent的值,让我们的请求可以快速的通过日志库查询到,具体的步骤就是: a. 拷贝登录后的浏览器中的cURL值,如图所示: 图2 b. 修改拷贝出来的CURL命令中的http_user_agent值,如下所示: $ curl -k 'https://erpuat.mailang.com/std/xxxxxx/xxxxxxx?mode=3&autoTitle=true&_mp=blank&oid=xxxxxx&_hid=xxxxxx&title=%E5%90%88%E5%90%8C%E5%8F%98%E6%9B%B4%E7%94%B3%E6%8A%A5%E9%98%B6%E6%AE%B5&_t=xxxxxx&_tFields=BUGUID%2CPROJGUID&BUGUID=xxxxxx' \ -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \ -H 'Accept-Language: zh-CN,zh;q=0.9' \ -H 'Cache-Control: max-age=0' \ -H 'Connection: keep-alive' \ -H 'Cookie: ASP.NET_SessionId=xxxxxxxxxxxxxxxxxxx; table_limit_4230bc6e-69e6-46a9-a39e-b929a06a84e8=20; keeplastname=xxxxxxx; _userHash=xxxxxxxx; __tracker_user_id__=xxxxxxxxxxxxxxxxxxxxxxx; __fast_sid__=xxxxxxxxxxxxxxxxx; userToken=xxxxxxxxxxxxxxxxxxxx; ck_login_out=xxxxxxxxxxxxxxxxxxxxx; table_limit_3d782708-71df-44de-0e66-08dacf924e4f=20' \ -H 'Referer: https://erpuat.mailang.com/PubPlatform/Login/prelogin?returnUrl=xxxxxxxxxxxxxxxxxxxxxx' \ -H 'Sec-Fetch-Dest: document' \ -H 'Sec-Fetch-Mode: navigate' \ -H 'Sec-Fetch-Site: same-origin' \ -H 'Sec-Fetch-User: ?1' \ -H 'Upgrade-Insecure-Requests: 1' \ -H 'User-Agent: mailang' \ -H 'sec-ch-ua: "Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "Windows"' \ -H 'x-fiddler-profiler: db,ar,http' \ --compressed 其中User-Agent的值就是我们要修改的http_user_agent的值,我们这里配置为mailang,如果这里没有配置的话,我们也可以直接通过-A mailang进行配置。由于执行的过程中,curl报证书问题,我们添加了-k参数进行忽略。 ...

March 16, 2026

某客户k8s集群连接kafka性能优化

1. 前言 最近k8s生产环境整体负载持续在很高的水位,此问题会导致应用启动时间过长从而导致pod启动失败,并且影响集群所有应用的运行效率,需要尽快定位到问题根源。 2. 定位问题 经过沟通以及排查,我们发现:172.16.9.195节点1分钟load高达45,而此节点的配置为8C/64GB。这样的负载已经是很高了,迫切需要进行优化 $ top - 14:34:56 up 932 days, 23:57, 1 user, load average: 45.89, 41.83, 38.25 Tasks: 241 total, 1 running, 240 sleeping, 0 stopped, 0 zombie %Cpu(s): 61.3 us, 7.6 sy, 0.0 ni, 27.4 id, 0.0 wa, 0.0 hi, 3.6 si, 0.0 st KiB Mem : 65976636 total, 4713772 free, 41757256 used, 19505608 buff/cache KiB Swap: 0 total, 0 free, 0 used. 23686668 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8727 root 20 0 11.9g 6.2g 10436 S 165.6 9.8 2420:42 java 23525 root 20 0 9864104 4.5g 10220 S 164.2 7.1 15681:36 java 24177 root 20 0 7171172 2.2g 9752 S 107.6 3.6 12076:04 java 17086 root 20 0 9881056 4.5g 10524 S 46.0 7.2 595:16.55 java 22195 root 20 0 9262612 3.4g 10348 S 38.1 5.5 267:17.53 java 3891 root 20 0 9932.6m 4.5g 9684 S 17.2 7.1 2826:10 java 1788 root 20 0 9102056 2.6g 11160 S 10.9 4.1 8:10.08 java 1660 root 20 0 5832736 904860 21556 S 9.9 1.4 69179:41 dockerd 3936 root 20 0 3650784 130264 23548 S 7.3 0.2 78787:15 kubelet 19873 root 20 0 9458468 2.8g 10428 S 6.3 4.4 70:30.53 java 68 root 39 19 0 0 0 S 4.0 0.0 1312:02 khugepaged 14540 root 20 0 1145376 216332 15616 S 3.6 0.3 3536:29 ilogtail 4053 root 10 -10 151228 33936 10612 S 2.0 0.1 3157:28 AliYunDunMonito 3 root 20 0 0 0 0 S 1.3 0.0 22133:15 ksoftirqd/0 23172 root 20 0 9184824 4.2g 9588 S 1.0 6.7 194:10.94 java 7 root 20 0 0 0 0 S 0.7 0.0 6099:02 rcu_sched 315 root 20 0 162148 4468 3664 R 0.7 0.0 0:08.21 top 1367 root 20 0 1022444 19184 452 S 0.3 0.0 5724:49 /usr/local/clou 4032 root 10 -10 102676 12024 8448 S 0.3 0.0 434:03.11 AliYunDun 23574 root 20 0 8306252 1.5g 9632 S 0.3 2.3 56:01.46 java 1 root 20 0 52596 4664 2384 S 0.0 0.0 870:26.31 systemd 2 root 20 0 0 0 0 S 0.0 0.0 1:32.01 kthreadd 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 9 root 20 0 0 0 0 S 0.0 0.0 2579:17 rcuos/0 10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcuob/0 11 root rt 0 0 0 0 S 0.0 0.0 4:37.08 migration/0 12 root rt 0 0 0 0 S 0.0 0.0 3:03.49 watchdog/0 ## 通过上面的top命令可以看到pid为 8727、23525、24177的这3个服务CPU使用率很高,我们把服务名称过滤出来看是什么服务 $ ps -ef | egrep '8727|23525|24177' root 8727 8705 99 May30 ? 1-16:21:16 /usr/java/latest/bin/java -javaagent:/alidata/agent/skywalking-agent.jar -Dskywalking.logging.output=CONSOLE -XX:-OmitStackTraceInFastThrow -Xms6144m -Xmx6144m -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:NewRatio=1 -XX:+DisableExplicitGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:/home/admin/logs/app/gc -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=20 -XX:GCLogFileSize=100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/alidata/dump/order-10.233.34.130.hprof -Dapollo.meta=http://apollo-configserver:8080 -jar -Xms6144m -Xmx6144m -XX:-OmitStackTraceInFastThrow /alidata//app.jar --server.port=8080 root 23525 23505 99 May24 ? 10-21:22:09 /usr/java/latest/bin/java -javaagent:/alidata/agent/skywalking-agent.jar -XX:-OmitStackTraceInFastThrow -Xms4096m -Xmx4096m -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:NewRatio=1 -XX:+DisableExplicitGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:/home/admin/logs/app/gc -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=20 -XX:GCLogFileSize=100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/alidata/dump/share-stock-10.233.34.132.hprof -Dapollo.meta=http://apollo-configserver:8080 -jar -Xms4096m -Xmx4096m -XX:-OmitStackTraceInFastThrow /alidata//app.jar --server.port=8080 root 24177 24155 98 May23 ? 8-09:16:26 /usr/java/latest/bin/java -javaagent:/alidata/agent/skywalking-agent.jar -XX:-OmitStackTraceInFastThrow -Xms2048m -Xmx2048m -XX:MaxMetaspaceSize=512m -XX:MetaspaceSize=512m -XX:NewRatio=1 -XX:+DisableExplicitGC -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:/home/admin/logs/app/gc -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=20 -XX:GCLogFileSize=100m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/alidata/dump/app-log-service-10.233.34.145.hprof -Dapollo.meta=http://apollo-configserver:8080 -Dapp.webapi.uri=http://app-webapi:8080 -jar -Xms2048m -Xmx2048m -XX:-OmitStackTraceInFastThrow /alidata//app.jar --server.port=8080 我们根据上面的命令可以看到占用大量CPU资源的是:order、share-stock、app-log-service,我们又观察了集群的其他节点,最终确认是order应用和share-stock应用占用了大量的CPU资源,这两个服务我们以前都反复的通过火焰图和抓包分析过很多次了,大量的CPU资源都是被连接kafka的相关操作消耗掉的,而我们跟开发沟通过,这两个服务本身就会依赖kafka,所以火焰图和网络包中会大量的出现kafka的身影不足为奇,基于以上情况我们建议:既然目前无法对order应用和share-stock应用进行性能优化,两个应用都是CPU资源的消耗大户,在集群中其他的节点计算资源还是充足的情况下,建议通过k8s的反亲和性,把这两个应用的pod分布在不同的节点来缓解CPU资源不足导致的性能问题。 ...

March 16, 2026

某客户mysql数据库线程池泄露

1、故障爆发 12月1号上午10点出头,我们收到阿里云监控告警:客户官网探测异常,如图所示: 然后我们DBA查看了后端数据库实例,发现数据库连接已经被用尽了,导致服务出现异常,如图所示: 当时我们和客户协商之后决定对数据库会话进行kill处理,如图所示: 经过临时处理之后,应用恢复正常,如图所示: 2、再次出现故障 在14:16分,客户再次联系我们,反馈成有部分接口超时,如图所示: 由于客户的服务底层代码为Go,我们之前建议过把代码里面加入pprof进行debug,否则出现问题我们没有办法看底层的线程池和堆栈信息。在这种情况下,我们尝试通过tcpdump抓取网络包,用来分析go应用到底在干什么。通过wireshark解包后,我们发现了异常情况:go应用和mysql数据库之间进行了大量的TCP Keep-Alive网络包交互,但是没有正常的SQL查询交互,如图所示: 我当时就判断:应该是go应用存在数据库连接池泄露,导致应用的数据库连接池用尽,最终出现如上图的情况,只有TCP Keep-Alive,没有正常的交互SQL。但是因为没有pprof,再加上是业务高峰期,我们无法定位到泄露代码。客户临时重启应用进行修复。 3、业务低谷问题复现 加入pprof之后,我们跟踪了goroutine,根据跟踪的图,我们还是没有办法定位到故障代码,如图所示: 这种情况下,问题似乎走入了死胡同。我想了一下:我们之前网络抓包的时候,应用已经处于假死状态了,导致我们无法看到到底是因为什么SQL导致的,如果我们把应用重启,在服务刚开始的时候就进行网络抓包,应该是能抓到问题SQL。我们再次进行抓包,这次发现了异常SQL:每个连接数据库的TCP连接,最终退出的时候,都执行了开启事务。如图所示: 最终定位到问题代码为以下代码,如图所示: 我们当时建议在判断if err的时候,添加回滚操作。但是客户还是想深入排查为什么会出现此bug。 4、彻底解决bug 我再次分析了网络包,发现出现问题的TCP线程池为101个。而我们在pprof跟踪的图上面刚刚好看到对应数量的goroutine。如图所示: 我们发现很多人也遇到这种问题,而点赞最高的回答,如下所示: 您要确保Begin()、Commit()和Rollback()出现在同一个函数中。它使交易更容易跟踪,并让您确保它们通过使用defer. 这是一个这样的例子,它根据是否返回错误来执行 Commit 或 Rollback: func (s Service) DoSomething() (err error) { tx, err := s.db.Begin() if err != nil { return } defer func() { if err != nil { tx.Rollback() return } err = tx.Commit() }() if _, err = tx.Exec(...); err != nil { return } if _, err = tx.Exec(...); err != nil { return } // ... return } 这可能会有点重复。另一种方法是使用事务处理程序包装您的事务: ...

March 16, 2026

某客户被入侵挖矿排查案例

1、当时的出现的情况是:执行 top、w、netstat命令的时候,会出现卡住的情况,无法正常使用 2、我们上传新的top命令之后,只是看到CPU使用率比较高,但是看不到占用CPU的异常进程 3、我们通过perf生成火焰图,发现存在很多异常进程占用CPU资源,这里基本上可以判定是中病毒了 4、但是我们定位不到异常的进程是什么,我们通过tcpdump抓取网络流量,看看通过网络层面有没有存在异常 5、我们通过bing搜索了 www.xmr-monero.top 和 www.fullskystar.top ,第一个跳出来的就是交易比特币的网站,第二个直接就跳出了被挖矿入侵的相关案例 6、通过搜索出来的CSDN的文章,我们根据他排查的步骤来进行:查看ldd /usr/bin/ls,对比了正常的服务器和异常的服务器 我们可以发现像文章中说的一样,我们的命令也被加入了 /lib/libcurl.so.2.17.0 动态库 7、但是我们搜索不到这个动态库文件,我们按照文章上面的操作步骤下载 busybox进行操作,busybox可以理解为一个干净的Linux系统,因为我们原来的系统已经被攻陷了,很多命令都被篡改了,所以要使用busybox $ wget https://busybox.net/downloads/binaries/1.28.1-defconfig-multiarch/busybox-x86_64 --no-check-certificat $ mv busybox-x86_64 busybox $ chmod +x busybox $ ./busybox ls -al /etc/ld.so.preload -rw-r--r-- 1 root root 22 Jul 24 21:53 /etc/ld.so.preload $ ./busybox cat /etc/ld.so.preload /lib/libcurl.so.2.17.0 $ ./busybox ls -al /lib/libcurl.so.2.17.0 -rwxr-xr-x 1 root root 31336 Jul 24 21:53 /lib/libcurl.so.2.17.0 $ ./busybox sh $ ./busybox chattr -i /lib/libcurl.so.2.17.0; ./busybox mv /lib/libcurl.so.2.17.0 /lib/libcurl.so.2.17.0.old exit 8、通过上面的步骤,我们可以看到病毒是通过 /etc/ld.so.preload 里面配置/lib/libcurl.so.2.17.0 进行进程隐藏的,我们可以通过 grep libcurl /proc/*/maps 查看到底有多少异常进程在运行 ...

March 16, 2026

某客户证书过期问题

周末接到小伙伴的电话,说是客户遇到问题了,但是她有事要去办理,那我们就接下来看一下到底是怎么回事。 1、首先了解情况:客户的SSL/TLS证书要过期了,所以进行了证书替换工作,但是替换之后,有一部分客户端还是提示证书已过期,如图所示: 注:我自己无法触发这问题,这里是其他小伙伴的截图 2、看这个报错是非常的清晰的,就是证书过期的问题,但是为什么同事没找到过期证书配置在哪里?是不是存在WAF或者CDN之类的中间层? 我们通过DNS可以看到确实是解析到阿里云对应是SLB上面,跟小伙伴的说法也是对得上的。我们已经详细的排查了SLB以及对应的NGINX-ingress后端服务,发现证书确实已经替换为新证书了。 3、这个时候阿里云的售后工程师反馈说:可能是ingress的一个bug,因为我们替换证书的时候,不是新建一个新的secret,而是在老的secret上面进行修改,有可能触发了NGINX的bug,导致有部分站点的证书并没有被替换掉 4、我们新建了一个secret,并全部执行了替换操作,但是结果移动端还是一样的报错信息。这就说明不是这个问题 5、客户怀疑我们之前升级k8s的时候,由于阿里云ACK的限制,我们把SLB由7层监听改为4层监听,证书也由SLB层下放到了ingress层,是不是ingress层存在某种限制?我们测试了7层监听,发现确实没有证书报错了。但这只是简单的测试,我们也不能确定,并且现在系统只是部分用户不能正常使用,我们无法无损的情况下把4层监听切换到7层监听 6、我们通过浏览器控制台上面看到: 所有页面里面存在部分是使用http协议,是不是这里存在https/http协议混用的问题? 7、把情况反馈给客户之后,客户进行了排查,最终反馈是:PC端的页面就是这样的,移动端不存在此问题。到此问题没有太多的思路,由于大部分用户还是正常访问的,我们跟客户商定在业务低谷尝试SLB 4层监听切换为7层监听。 8、在不影响业务的情况下,我们还是想再进行一次确认操作。我们通过kubectl krew ns 和 kubectl krew mtail 插件,对NGINX ingress 所有pod进行log跟踪,结果如图所示: 我的公网ip是 36.28.223.82,通过vim进行搜索,结果非常意外:我们通过日志确定请求没有落到NGINX ingress上面。由此我们得出两个可能: 1、请求没有到nginx-ingress;2、TLS或者TCP握手失败。 9、通过上面的日志,我们得出两个可能。但是我们还要再次确认,到底是怎么回事。我们通过tcpdump进行抓包分析,结果如图所示: 我们通过wireshark分析了我们抓取到的数据包,跟我们在第8步跟踪日志得出的结论是相对应的。不过这里更近一步,连TCP的连接都没有建立。 10、客户跟我们反馈过:他们前段时间开通了对ipv6协议栈的支持,并且我们步骤1通过nslookup也查询到了相关的解析,那么是不是用户通过ipv6协议进行的访问,我们没有配置ipv6相关的证书。之前我一直无法复现问题,客户告知我,通过移动端4G/5G 可以稳定触发。我通过4G确实触发了此问题,我建议客户关闭ipv6的DNS解析,我们再进行尝试。结果如图: 我们停止了ipv6的DNS解析,但是访问还是异常。这时候确实不确定问题的根源,但是肯定不是 SLB 7层监听跟4层监听的问题。我们在手机上面抓包又非常的麻烦。 11、最终客户反馈:确实是ipv6证书的问题,他们的ipv6是通过电信做的。他们把证书交给电信之后,访问就恢复正常了。我们之所以暂停ipv6解析之后,还是存在问题,估计是 LDNS缓存导致的。我们通过电信云官网了解到: 确实是支持https加密传输,说明问题确实是在ipv6这里。 总结:经历了这么多波折,最终才定位到是ipv6的问题,主要原因是我自己无法复现问题。在国家大力推广ipv6的大环境下,ipv6可能会越来越普及。大家需要尽快熟悉ipv6,我自己是连夜调整了自己的网络适配了ipv6。 引用1: https://en.wikipedia.org/wiki/IPv6 引用2: https://www.ctyun.cn/document/10018847/10018856

March 16, 2026