前言

  买完服务器2核4G部署几个中间件内存占用率就80%了,咋办呢😡,其实你忽略了调优

1.容器情况

1.1 首先得知道进程的运行状态

     1.1.1   实时观察一下资源占用情况

1.top   //实时查看资源占用情况  
2.ps -aux   //ps是进程的缩写。aux是allUser給人看的。列多、直观,重点看CPU和内存资源占比
3.ps -ef     //ef是everyfull是所有的意思。特点是列少但是啥都有,适合看父子进程关系

1.1.2 我执行了top其中的%MEM是内存列,发现有一个占用达到了25.0%一个进程占内存的1/4,必须优化他

1.1.3 其中PID是进程ID,看看他是谁吧(悄悄告诉你,其实ps aux也可以直接去找)

1. ps -ef   //运行中的进程
2. ps -aux |grep 31024    //从所有进程中拿到 31024信息
3. ps -ef |grep nacos   //nacos进程和grep临时进程
4. ps -ef |grep nacos |grep -v grep  //纯Nacos进程





简述啥意思:
1.  grep是匹配字符串的功能
2.|是管道符,前面的数据作为后者的原料,比如ps -aux 是所有用户视角下的所有进程,那么我用| 所有进程信息就是原料,我去grep匹配字符串31024。
3. -v 是“非”的意思,也就是排除掉。grep指令会出现临时进程,grep nacos这个进程又含有nacos信息所以被抓出来了,你会看到俩进程。grep -v grep本身不出现在查询的结果,作用是排除上个管道的“grep”进程数据
 

  我执行了 ps -aux |grep 31024找到了nacos的信息,问题是看不懂哇咋办呢(注意看!第一个是不是抓nacos的时候临时产生的grep进程!)

 1.1.4 表头信息一块打印出来就行了呗

1. ps -aux |head -1  //head 横杠1不是负1奥,head -1是拿到前一行。
2. ps -aux |head -1 ; ps -aux | grep nacos   // 表头和某行数据无缝衔接用“;”来隔开就可以同时展示了

2.JVM的理论知识(不深究的可以跳过)

  那我知道了每一项都是啥意思了。仔细看后面看不懂那串东西。其实学过Java的同志很熟悉,这是JVM虚拟机的参数呗。給不知道的同志补补JVM虚拟机的知识

2.1  虚拟机的对象生命周期,分区,GC垃圾回收机制。JVM的基础调优。

      2.1.1 分区 

  以JDK8以及以后为例子。在JDK8里面JVM内存模型是是新生代,老年代,元空间(以前叫永久代),每个对象头一方面有java对象的锁机制信息(无锁,轻量锁,偏向锁,重量锁),而另一方面有对象的生存时间,线程时间等等。对象创建会放到堆内存空间,对象在代码里面被另一个对象引用分为了强,软,弱,虚,终结器引用,咱们写的都是强引用,软引用需要引入软引用对象泛型是当前的对象,弱虚是需要依赖引用队列,终结器现在已经不用了。铺垫完成,GC垃圾回收器会在老年代空间不足、元空间不足、显式调用System.gc()、新生代晋升老年代失败,等时候分片对堆内存空间进行回收。如果对象被强引用那就不回收,被软引用则内存紧张时的下次GC再回收,软弱下次GC直接回收掉。MinorGC只回收新生代,fullGC回收所有(会阻塞所有线程哦,有概率会影响分布式锁原子性),现在规定回收扫过15次每次年龄+1,如果年龄已经15岁了都没有被回收的对象就可以放到老年代啦~特点是只有FullGC才可以进行回收。现在的问题是,我給Nacos分了1G的内存来給Nacos的虚拟机存对象,放啥要塞1G啊?干鸡毛呢,问题出在这了哦。

2.1.2JVM内存模型

  新生代分为了伊甸园(取名来自古老的传说),幸存区分为了(From,To)
为啥这么分?幸存区为了避免内存碎片太多,所以采取“左手倒右手”的方法尽可能减少内存碎片,右手TO永远是空的。项目部署启动后GC垃圾回收扫新生代,新创建的对象在伊甸园区,没被回收的对象放到了To区,右手得是空的,把数据放到TO区,然后From和TO对调,From有数据,TO是空的。第二次GC垃圾回收,没被回收的伊甸园对象放到了TO区,From区没被回收的也放到了TO区,这时候要陶腾手了,把From左手清空(备份都在TO区呢),然后TO区的所有对象转移到From左右,这时候TO区空了,循环就可以了。
  注意!实际上不会左右手转移数据多费性能呀,“左右手”是不被定义的,所以本质不是数据的转移是命名的改变。下面是我画的草图哦


 

2.1.3小总结

GC内存模型是不是非常好理解呢,掌握JVM基础知识有助于后续的调优理解哦,当然啦这个不是必须要掌握的(Java程序员除外)。所以給Nacos初始大1G堆内存,空间給的太大了,触发GC的触发点和触发频率会降低,造成了浪费。

3.JVM参数调整

 3.1Nacos初始JVM参数调整

         一开始用的镜像是nacos/nacos-server:v2.1.0-slim 这个是“瘦身”版的,所以不好看MinorGCFullGC的执行频率。dp给个粗略指标:

一、Minor GC
正常:几小时甚至一天几次

需要关注:每小时超过10次

立即排查:每分钟超过1次

二、Full GC
正常:几乎为0(几天甚至几周一次)

需要关注:每天发生1次

立即排查:每小时发生1次

三、GC停顿时间
Minor GC停顿:超过 100ms 需要关注

Full GC停顿:超过 500ms 需要立即排查

四、内存趋势
容器内存(docker stats):持续增长,24小时内涨幅超过20% 需要关注

老年代使用率:每次Full GC后仍持续在 70%以上,需要关注

   重写拉取一下Nacos吧,这次设定JVM参数,我就十几个服务器,百来条配置项所以设置的没那么大,后期不合适再排查修改

docker run -d \
  --name nacos \
  --env-file /etc/nacos/custom.env \
  -p 8848:8848 -p 9848:9848 -p 9849:9849 \
  -e JVM_XMS=256m \
  -e JVM_XMX=256m \
  -e JVM_XMN=128m \
  --network=zhhx \
  --restart=always \
  nacos/nacos-server:v2.1.0-slim

  现在的RES大概 532 MB,比堆内存稍高一点正常的堆外内存开销,内存占比也是减半了。CPU  0.7%,运行稳定没毛病

更多推荐