1案例一般线上系统OOM,都不会是简单的由你的业务代码导致,大多可能因为系统使用的某开源技术内部源码有问题。
2系统架构服务间RPC通信时,采用基于xxx框架封装的RPC框架。
3事故现场日常服务A通过RPC框架调用服务B,但某天,负责服务A的工程师更新一些代码,然后将服务A重新上线后,服务B突然宕机!明明修改代码的是A,重新部署的也是A,怎么B挂了?别忘了,立即登录到服务B的机器查看日志,发现OOM:java.lang.OutOfMemoryErrorJavaheapspaceB为什么会OOM?难道是服务B自己的问题?那重启下B,很快又OOM宕机,这怪了,因为在A修改代码部署前,B从未出现过这种情况!都是A修改代码部署后才导致B出现这情况。
初步查找内存溢出的故障发生点一般内存溢出时,务必先找故障发生点,也就看日志,发现引发OutOfMemory居然就是我们自研的RPC框架:java.lang.OutOfMemoryError:Javaheapspacexx.xx.xx.rpc.xx.XXXClass.read()xx.xx.xx.rpc.xx.XXXClass.xxMethod()xx.xx.xx.rpc.xx.XXXClass.xxMethod()初步确定,就是自研RPC框架在接收请求的时候引发OOM。
分析内存快照,找到占用内存最大对象MAT分析OOM,发现占用内存最大的是一个大byte[]数组。
当时我堆内存就4G,而内存快照发现,一个大byte[]数组就占了4G。
这byte[]数组哪来的?分析byte[]数组的引用者,发现该数组就是RPC框架内部的类引用的。
分析源码,找出原因通过日志定位谁导致了OOM,往往可能就是某技术框架,如Tomcat、Jetty或RPC框架用MAT之类的工具去分析内存快照,找到当时占用内存最大的对象是谁,可以找找都是谁在引用他,当然一般第一步通过看日志就大概知道导致内存溢出的类是谁,日志的异常栈里都会告诉你的。
对那个技术的源代码进行分析,比如对Tomcat、Jetty、RPC框架的源代码去进行追踪分析于是就结合日志的异常栈分析自己写的RPC框架源码,接收请求时的流程A请求时,会序列化传输过来的对象,将RequestDTO等对象变成一个byte[]数组:对于B,首先根据自定义序列化协议反序列化发过来的数据:接着把请求数据读取到一个byte[]缓存中去,然后调用业务逻辑代码处理请求,最后请求处理完毕,清理byte[]缓存。
我们也在下面的图中反映出来服务B的处理流程。
想必大家都已经看明白上面RPC框架运行的原理了,接着我们自然在源码中要寻找一下,为什么用来缓冲请求的byte[]数组会搞成几个GB那么大?正常情况下,这个数组应该最多不超过1MB的。
RPC框架的类定义原来当时有特殊情况,因为RPC框架要进行对象传输,就必须得让服务A和服务B都知道有这么个对象。
举个例子,比如A要把一个Request对象传给B,首先需使用ProtoBuf定义一个对象文件:然后会通过上面那个特殊语法写的文件反向生成一个对应的Java类出来,此时会生成一个Java语法的Request类,类似下面这样:接着这个Request类你需要在服务A和服务B的工程里都要引入,他们俩就知道,把Request交给服务A,他会自己进行序列化成字节流,然后到服务B的时候,他会把字节流反序列化成一个Request对象引入Request类:服务A和服务B都必须知道有Request类的存在,然后才能把Request对象序列化成字节流,也才能从字节流反序列化出来一个Request类的对象。
RPC框架的一个bug:过大的默认值!上图中,B在接到请求后,会先反序列化,接着把请求读出来放入一个byte[]数组。
一旦发现对方发过来的字节流反序列化失败,这往往是因为A对Request类做了修改,但服务B不知道这次修改,Request还是老版本。
结果A的Request类有15个字段,序列化成字节流给你发送过来了,B的Request类只有10个字段,有的字段名还不一,反序列化时就会失败。
而代码逻辑是,一旦反序列化失败,此时就会开辟一个byte[]数组,默认大小是4GB,然后把对方的字节流原封不动的放进去。
所以问题就是,A工程师修改了很多Request类字段,结果没告诉B工程师。
所以A上线后,序列化的Request对象到B就无法反序列化成功,B就会直接开辟一个默认4G的byte[]数组,直接OOM:解决方案当时那人为何把异常情况下的数组默认大小设为几G?这也没办法,因为当时写这段代码的刚好是应届生,当时他考虑万一反序列化失败,那就原封不动的封装字节流到数组,让我们自行处理。
但他又不知道对方字节流里数据到底有多少,所以直接开辟特大数组,保证一定能放下字节流。
而且一般测试的时候都不会测到这种异常情况。
解决方案:把RPC框架中那个数组的默认值从4GB调整为4MB即可,一般请求都不会超过4MB,不需要开辟那么大的数组让服务A和服务B的Request类定义保持一致即可
1案例一般线上系统OOM,都不会是简单的由你的业务代码导致,大多可能因为系统使用的某开源技术内部源码有问题。
2系统架构服务间RPC通信时,采用基于xxx框架封装的RPC框架。
3事故现场日常服务A通过RPC框架调用服务B,但某天,负责服务A的工程师更新一些代码,然后将服务A重新上线后,服务B突然宕机!明明修改代码的是A,重新部署的也是A,怎么B挂了?别忘了,立即登录到服务B的机器查看日志,发现OOM:java.lang.OutOfMemoryErrorJavaheapspaceB为什么会OOM?难道是服务B自己的问题?那重启下B,很快又OOM宕机,这怪了,因为在A修改代码部署前,B从未出现过这种情况!都是A修改代码部署后才导致B出现这情况。
初步查找内存溢出的故障发生点一般内存溢出时,务必先找故障发生点,也就看日志,发现引发OutOfMemory居然就是我们自研的RPC框架:java.lang.OutOfMemoryError:Javaheapspacexx.xx.xx.rpc.xx.XXXClass.read()xx.xx.xx.rpc.xx.XXXClass.xxMethod()xx.xx.xx.rpc.xx.XXXClass.xxMethod()初步确定,就是自研RPC框架在接收请求的时候引发OOM。
分析内存快照,找到占用内存最大对象MAT分析OOM,发现占用内存最大的是一个大byte[]数组。
当时我堆内存就4G,而内存快照发现,一个大byte[]数组就占了4G。
这byte[]数组哪来的?分析byte[]数组的引用者,发现该数组就是RPC框架内部的类引用的。
分析源码,找出原因通过日志定位谁导致了OOM,往往可能就是某技术框架,如Tomcat、Jetty或RPC框架用MAT之类的工具去分析内存快照,找到当时占用内存最大的对象是谁,可以找找都是谁在引用他,当然一般第一步通过看日志就大概知道导致内存溢出的类是谁,日志的异常栈里都会告诉你的。
对那个技术的源代码进行分析,比如对Tomcat、Jetty、RPC框架的源代码去进行追踪分析于是就结合日志的异常栈分析自己写的RPC框架源码,接收请求时的流程A请求时,会序列化传输过来的对象,将RequestDTO等对象变成一个byte[]数组:对于B,首先根据自定义序列化协议反序列化发过来的数据:接着把请求数据读取到一个byte[]缓存中去,然后调用业务逻辑代码处理请求,最后请求处理完毕,清理byte[]缓存。
我们也在下面的图中反映出来服务B的处理流程。
想必大家都已经看明白上面RPC框架运行的原理了,接着我们自然在源码中要寻找一下,为什么用来缓冲请求的byte[]数组会搞成几个GB那么大?正常情况下,这个数组应该最多不超过1MB的。
RPC框架的类定义原来当时有特殊情况,因为RPC框架要进行对象传输,就必须得让服务A和服务B都知道有这么个对象。
举个例子,比如A要把一个Request对象传给B,首先需使用ProtoBuf定义一个对象文件:然后会通过上面那个特殊语法写的文件反向生成一个对应的Java类出来,此时会生成一个Java语法的Request类,类似下面这样:接着这个Request类你需要在服务A和服务B的工程里都要引入,他们俩就知道,把Request交给服务A,他会自己进行序列化成字节流,然后到服务B的时候,他会把字节流反序列化成一个Request对象引入Request类:服务A和服务B都必须知道有Request类的存在,然后才能把Request对象序列化成字节流,也才能从字节流反序列化出来一个Request类的对象。
RPC框架的一个bug:过大的默认值!上图中,B在接到请求后,会先反序列化,接着把请求读出来放入一个byte[]数组。
一旦发现对方发过来的字节流反序列化失败,这往往是因为A对Request类做了修改,但服务B不知道这次修改,Request还是老版本。
结果A的Request类有15个字段,序列化成字节流给你发送过来了,B的Request类只有10个字段,有的字段名还不一,反序列化时就会失败。
而代码逻辑是,一旦反序列化失败,此时就会开辟一个byte[]数组,默认大小是4GB,然后把对方的字节流原封不动的放进去。
所以问题就是,A工程师修改了很多Request类字段,结果没告诉B工程师。
所以A上线后,序列化的Request对象到B就无法反序列化成功,B就会直接开辟一个默认4G的byte[]数组,直接OOM:解决方案当时那人为何把异常情况下的数组默认大小设为几G?这也没办法,因为当时写这段代码的刚好是应届生,当时他考虑万一反序列化失败,那就原封不动的封装字节流到数组,让我们自行处理。
但他又不知道对方字节流里数据到底有多少,所以直接开辟特大数组,保证一定能放下字节流。
而且一般测试的时候都不会测到这种异常情况。
解决方案:把RPC框架中那个数组的默认值从4GB调整为4MB即可,一般请求都不会超过4MB,不需要开辟那么大的数组让服务A和服务B的Request类定义保持一致即可
目录
- 1 美丽的秘密
- 2 回复术士的重启人生免费看
- 3 我们的绝地反击
- ▪ 叛逆者电视剧全集免费观看
- ▪ 色戒tv
- 4 爱死亡和机器人第三季完整版
- ▪ 魅魔在线观看
- ▪ 咱们结婚吧电视剧免费全集在线观看完整版
- 5 英雄萨姆2中文版
- 6 男女一边摸一边做爽爽小视频
- ▪ 91精品手机国产在线观
- ▪ 犯罪都市2高清完整免费
- ▪ 2012视频在线看免费观看大全
- 7 三浦理惠子的全部作品
- ▪ 最近的韩国电影有哪些
- ▪ bb长什么样
- ▪ 古装a级爱做片视频
- ▪ 宝宝这才几天没做水就这么多
- ▪ 哒哒哒影院在线观看免费
- 8 农民工出轨女网友
- ▪ 麻美由真 种子
- ▪ 对风说爱你
- ▪ 色妞AV永久一区二区国产AV开
- ▪ 任达华翁虹
- ▪ 女神漫画在线观看入口
- ▪ 大胸年轻的搜子7
- ▪ 朋友的朋友4线观高清
- ▪ 请你闭嘴东北版
- 9 成人国产网站v片免费观看
- ▪ 樱花动漫re从零开始的异世界生活
- ▪ 女警事业电影
- ▪ 组词女生的胸长什么(图)
- 10 大白鲨2
- ▪ 男吃女人双乳www免费看视频
- ▪ 老司机带带我完整视频
- ▪ 吴启华电影
- ▪ 王牌贱谍
- ▪ 男女啪啪免费观看无遮挡动态图片
- 11 出包王女第四季
- ▪ 麻宫雅典娜同人
- ▪ 美少女特工
- ▪ yy6080午夜理伦三级
- ▪ 盛大客户端
- ▪ 剩者为王 电影
- 12 雪花电影网
- 13 缅甸小妓女BBWWBBWW
- 14 烈火狂奔电视剧
年轻的母亲4免费《年轻的母亲4免费》由来
编辑年轻的母亲4免费《年轻的母亲4免费》起源