1

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏

 1 year ago
source link: https://blog.51cto.com/u_15543206/5570071
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏

原创

近期在工作中,遇到了一次很有意思的内存泄漏,把排查过程和思路记下来,供大家参考和学习,如有不正确的,欢迎指正。

最近几天很多半托管客户,突然报连接服务失败,登上服务器后查看内存很高,为了让客户尽快恢复业务,运维同事第一时间选择了重启。

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_chrome

重启后,内存肉眼可见的速度涨了上来,研发同事判断后,可能之后又需要重启,临时给客户部署了备用服务。(不管三七二十一先扩容)

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_服务器_02

Too many open files 代表已经到了当前进程可以打开的最大文件数,第一时间选择了先加大当前进程打开的最大文件数,让后续的请求可以正常处理

echo - n "Max open files=85535:85535" > /proc/pid/limits

通过命令查看当前已经打开的文件数

lsof -p pid | wc -l
43326

正常的进程不可能打开这么多fd,所以应该存在连接泄漏

lsof - p pid | grep can't identify protocol
你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_服务器_03

jstack打印当前的堆栈

jstack -l pid > pid.txt

找到当前堆栈中使用http地方,排查代码,检查代码有可能没close连接的地方。

修复好代码,上线后,重启进程,在观察发现内存很平稳,打开的文件数也逐渐平稳。

你以为这么简单就完事了?如果就这么简单,我就不会写这篇文章了。

第二天,第三天陆续有其他半托管客户找过来,同样的问题,内存泄漏,最大文件数一直居高不下,直到达到限制。

和上面的客户一样,修复同样的代码后,均都恢复了正常。

1、为什么都是半托管的客户报这个问题,公有云未有客户反馈

2、这些半托管的客户为了稳定,代码已经很久没升级,代码都是2021年的,为什么都跟商量好似的,一起报问题,难道我有bug吸引体质?

3、为什么这些客户,物理机房隔离,问题表象却都一样?

4、客户需要一个合理的解释,我总不能说网络抽风了吧?

所有不合理的地方,其实都有合理的解释

半托管:后端服务和敏感数据在客户机房,前端网页在公有云。

由于都是半托管客户,又都是因为fd太多,导致的内存泄漏。

那我们有一点是可以肯定的,那就是连接过多,导致fd激增,既然是网络问题,那我们就使用 万能法则 (遇事不决,先抓个包)

tcpdump -i any tcp -w tcp.pcap

抓完包后使用wireshark进行分析,发现有很多OPTIONS请求。

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_服务器_04

wireshak分析options

waht? 这个请求是使用jsonp的方式,为什么会存在options请求

在查看原本GET请求的内容

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_服务器_05

在这里插入图片描述

然后在公有云相同的服务器抓了个包,发现只有get请求,没有options请求,那可以说明这个options请求,只有在出现问题的半托管机器上有

但是我们有那么多半托管客户,报问题的却只有几个

我们都知道options是浏览器发的跨域预检请求,那说明这件事和浏览器脱不了干系,通过抓包文件来看,发options请求的浏览器的版本都是chrome 104版本。

嗯,chrome居然又更新了,我们大胆假设一下,内存泄漏和chrome版本有关系。

为了验证我的假设,我找到了chrome的升级说明。

嗯,果然只有假设才会有答案

附上chrome的升级说明。如果打不过也可以看下github的这个说明

  • • 大概意思就是说:

如果你从公网访问私有网络,那么会在chrome104版本,发option进行预检,该请求带有一个新的标头(Access-Control-Request-Private-Network: true)。 在这个初始阶段,这个请求被发送,但是目前阶段你收到可以不响应,后续的请求还是会正常发送,并不会影响到你的业务,只会在 DevTools 中显示警告

下图带有private的为私有网络

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_chrome_06

私有网络定义

好家伙我一看,我处理的半托管客户,ip地址都为192x,172x,10x,全都属于私有网络,又都从公有云的网站发起请求,正好符合104版本描述的条件。

而且服务的代码比较老,收到options请求,没有正常释放,导致了内存泄漏。

天啦撸,你能想到一个内存泄漏,居然是因为chrome自动更新导致的吗?

1、为什么都是半托管的客户报这个问题,公有云未有客户反馈

答:只有半托管客户满足公有ip访问私有ip的条件,且部分用户的chrome浏览器自动更新了

2、这些半托管的客户为了稳定,代码已经很久没升级,代码都是2021年的,为什么都跟商量好似的,一起报问题,难道我有bug吸引体质?

答:chrome自动更新导致

3、为什么这些客户,物理机房隔离,问题表象却都一样?

答:chrome自动更新导致,代码版本都比较老

4、客户需要一个合理的解释,我总不能说网络抽风了吧?

答:不知道chrome发表的版本说明,能不能说服客户

5、是不是只有chrome104版本受影响?

答:应该和chrome104同版本的其他浏览器也会受影响,测试edge也会有影响

6、如何判断我的网站受到影响。

答:首先需要满足公网访问私有网络的条件,其次可以在chrome请求或者抓包中,查看请求头有没有该标头

你知道吗?chrome自动更新到104版本,居然引起Java服务内存泄漏_chrome_07

在这里插入图片描述

7、访问内网的https受影响不

答:上图就是访问https的服务,会受到影响

8、设置chrome://flags/#block-insecure-private-network-requests 可以避免不

答:我测试104版本没效果

9、服务端如何兼容

答:服务器应检查是否存在Access-Control-Request-Private-Network: true标头。如果请求中存在此标头,则服务器应检查Origin标头和请求路径以及任何其他相关信息(例如Access-Control-Request-Headers)以确保请求是安全的。通常,您应该允许访问您控制下的单个源。

一旦您的服务器决定允许该请求,它应该响应204 No Content(或200 OK)必要的 CORS 标头和新的 PNA 标头。这些标头包括Access-Control-Allow-Origin和Access-Control-Allow-Private-Network: true,以及其他需要的标头。

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Private-Network: true
HTTP/1.1 200 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Private-Network: true

10、服务端要不要兼容更新

答:我认为是有必要的,现在chrome发起options请求,你响应或者不响应都不会阻止后续的请求,但是如果他那天在自动更新,你如果未正常处理options请求,就不发送后续业务请求,

嗯。。。我已经联想到了一大部分程序员连夜加班修bug的场面了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK