跑得好好的Java进程,怎么突然就瘫痪了?
阿里妹导读:Java能成为应用最广泛的语言,和他的内存托管机制是分不开的。很多人眼中,Java虚拟机是透明的,只需知道核心api的用法,便可以专注于实现具体业务,然后依赖Java虚拟机运行甚至优化应用。
你是否有过这样的经历,跑得好好的Java进程,突然就瘫痪了。过于依赖Java虚拟机导致我们对问题无从下手,问题反复出现影响开发效率。其实,多数Java进程瘫痪的原因可以从java虚拟机层面找到原因,本文列举出导致Java进程瘫痪的一些共性原因,供大家交流和学习。
一、内存回收一直是java的痛点
用Java无法做出类似Redis这样的产品。java的内存回收机制使我们在编写代码时不需要关注对象的回收,同时加大了内存回收的消耗,标记复制需要做内存拷贝,标记清除算法则需要stop the world。所以我们在使用缓存的时候,量稍微大一些就需要借助类似Redis这样的中间件帮我们处理了。作为Javaer,我们享受了自动内存回收的安逸,同时也需要多了解下内存优化的方法。
二、为什么fgc停不下来了
1.什么情况下会gc
为了了解我们的系统为什么会不停fgc,我们需要先了解一下系统什么情况下会gc。在jvm层面,当我们new一个对象的时候,jvm会先在堆区分配对象需要的内存,这个时候如果内存不够的话,就需要gc了,gc的返回结果就是对象的空间地址。jvm会先进行ygc,也就是我们通常说的标记复制,如果ygc之后依然申请不到空间,就会进行fgc了。同理,如果fgc之后依然没有足够的空间,就会循环的进行fgc,直到申请到足够的空间。
2.导致不停的fgc的原因
如上文所讲,fgc有可能发生在你的每一行代码。如果fgc之后依然没有足够的空间,就会不停的fgc,直到申请到足够的空间。同时JVM会限制在抛出OutOfMemory错误之前在GC中花费的VM时间的比例。系统频繁FGC大致有五种情况:
- 内存泄漏
- 请求处理变慢导致同时申请内存的线程太多
- metaspace 耗尽
- 常量池将堆区占满
- 堆外内存耗尽
1w,正常情况下处理一个请求的时间是1ms,那同一时刻并行的请求数量仅为10。如果性能发生抖动,每个请求处理的时间增加到100ms,那同一时刻并行的请求数量就会增加到100个。每个线程在处理请求的时候都会new一些对象出来,长时间存活的线程会造成类似内存泄漏的效果,将系统的内存耗尽。同时fgc也会加剧系统性能的开销,使系统变得更慢,产生雪崩。
三、如何让系统fgc之后仍然能活下来
1.杜绝内存泄漏
内存泄漏造成系统瘫痪的频率很高,有些系统定时从数据库拉取配置信息缓存到集合中,但是set不小心写成了list,最终在新增元素的时候内存溢出了。养成良好的编程习惯,多关注些细节,就能避免很多未知的问题。
2.并发限制:防止系统被撑死
每台服务器都有并行处理请求的上限,不管请求处理的多快,超过上限之后就会被撑死,对高并发的请求做好并发数限制是保持系统稳定的必要条件。需要注意的是,有一些系统在拒绝过多的请求时,也会做一些降级逻辑,降级逻辑也是有性能开销的,同样需要做并发限制,如果降级的请求超过并发限制,将不进行降级逻辑直接抛出异常。我们可使用的限流组件有很多,推荐我们阿里自研的Sentinel 和 Netflix开源的Hystrix。
3.自适应限流:防止系统被摸死
我们需要自适应限流有两个原因:
a. 每台服务器所处的环境是不一样的
有些服务器和离线计算的vm混部在一起,有些部署在实体机,有些部署在新老型号的机器上,每台服务器能承受的qps并不完全一样。统一配置分布式系统中每台服务器限流阀值,要么发挥不出每台服务器应有的作用,要么在高qps的情况下一些比较慢的服务器宕机,所以用服务器作为限流粒度是最合适的。
b.设置了正确的限流阀值,也可能被摸死
当单机承受的QPS 6~20倍于限流的流量时,拒绝一次请求的开销就无法忽略不记了。譬如春晚活动有些系统设置了正确的限流也被6~20倍于限流的流量冲垮。这种死法称为被摸死。应对这种情况,我们可以做的是在受到6~20倍的大流量时,动态减少限流的阀值。比如系统最开始接受1000qps,5000的拒绝流量过来会把系统摸死,这个时候我们调整系统的阀值,限流设置到100,被摸死的阀值就可以高一些,这样就算有6000个请求进来,我们系统也可以保证活下来。
4.异常流量监控:防止长尾请求拖垮系统
我们盯系统监控的时候通常会关注99分位的数据,但如果设置了合理的限流,系统依然被流量打挂,就要从那百分之一的长尾数据入手了。有些长尾数据对系统的影响会非常大。想象如果一个put请求传过来几十兆的数据,对java是极为不友好的,很有可能产生fgc,让请求变慢,导致一系列问题。
总之,磨刀不误砍柴工,当我们的系统因为fgc一次又一次重启的时候,不如花时间了解下系统产生性能问题的原因,将产生问题的那根针拔掉,晚上睡个安稳觉,白天更加充满活力的挖新坑。希望每个程序员手里都是一个稳定的系统。
参考资料:
jvm调优总结:
https://hllvm-group.iteye.com/group/wiki/?category_id=301
诺亚(Noah)自适应限流 稳定性利器 :
https://www.atatech.org/articles/149208
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
5G方兴未艾,探索6G是否为时过早?
来源:北京物联网智能技术应用协会 近日,从科技部官网获悉,我国正式启动6G移动通信技术的研发工作。 科技部表示目前全球6G技术研究仍处于探索起步阶段,技术路线尚不明确,关键指标与应用场景还未有统一的定义,科技部将联合专家组系统开展6G技术研发工作,探索可能的技术方向。 被称为5G元年的2019年即将步入尾声,但在5G基础设施建设的地图上仍有大片空白的位置需要填充,值此方兴未艾之际投入对6G的研发工作,是否为时过早呢。 以史为镜,可以知兴替。我们来瞧瞧移动通信的发展或许可以找到答案。 “大哥大”时期日常中我们说的3G,4G不仅仅是网上冲浪速率的差距,也是移动通信系统断代的划分,简单来说1G我们可以称之为第一代模拟移动通信系统。 在1987年底我国第一代模拟移动通信系统开通并正式商用,当时的载体相信大家都知道是足足一斤重的“大
- 下一篇
记一次win server 2012的离线python环境安装(包括whl和setup.py)
目录 前言 python3 exe安装 pip whl安装 setup.py安装 最后 前言 总有某些公司是offline的, 你懂的, 然后用着古老的服务器. 所有有了这种奇怪的需求. 这里分成三个部分来说, 首先是py3的离线安装, 就是大家熟悉的exe安装. 然后是pip使用下载好的whl文件进行库的安装. 最后是使用setup.py进行安装. python3 exe安装 首先来到官网的Windows下载页, 选择合适的版本, 比如我选的py3.7.5的64位exe安装包: 然后就是常规安装, 记得勾选Add... 装完之后打开powershell测试一下: pip whl安装 然后下载必备的lxml文件, 选择对应的版本: 之后pip install whl文件路径即可. setup.py安装 为啥说python-docx典型呢, 因为它只有source, 没有whl文件. 然后进入目录, 运行python setup.py install即可.值得一提的就是, python-docx是依赖lxml的, 所以要先装lxml, 当然, py3的安装肯定是最先的. 最后 喜欢记得点...
相关文章
文章评论
共有0条评论来说两句吧...