整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

鸿萌的成功案例:天津某单位网站遭遇病毒挂马,硬盘空间

鸿萌的成功案例:天津某单位网站遭遇病毒挂马,硬盘空间全部占满

 天津市某文化馆网站服务器遭到病毒袭击。网站所在硬盘全盘空间占满,导致网站瘫痪。

如下是挂了木马的网页代码:

  经鸿萌工程师确认,这台网站服务器所中为最新的VBS病毒。这种病毒会感染网站文件,所有网站静态.html被挂了无限的代码,直到将整个分区完全占满。工程师看到客户存放网站文件的F盘500G已经没有一丝剩余空间。同时该病毒复制大量病毒代码到可执行文件中,只要计算机调用文件,即会传染更多文件。病毒进程如下:

  此次所遇到的病毒比较特殊,由于客户发现时间较晚,病毒已经把系统盘和网站所在分区硬盘空间占满,系统运行缓慢,没有任何缓存空间。致使无法使用杀毒软件或者专杀工具进行查杀。由于网站配置比较复杂,所有网页又被挂马感染,解决起来比较复杂。客户不想重做系统,于是我公司为其量身定做了个性化解决方案。

  首先,将网站程序、服务和病毒进程关闭,使病毒无法继续运行。

  其次,将中毒的系统和网站程序做一个全盘的镜像,保存原始数据,以备不测。

  然后工程师通过自定义批处理工具和手工双重查杀,利用自定义代码清除的批处理命令,将网站中数万个静态网页上面挂的病毒代码清理完毕,历时三天三夜的查杀,终于彻底清除了病毒。

  最后重新配置网站系统,将网站恢复运营。

少小伙伴在电脑应用的时候都会发现:通常自己只打开一个网页浏览,但是有的时候却感觉电脑运行不顺畅,打开资源管理器一看,处理器占用率不低,甚至会出现多个网页的线程……对于这个现象多年来也没人给一个合理的解释,不过最近微软终于主动现身解开了这个谜题。

很多人遇到这种情况,都会以为自己中了病毒,实际上并非如此。最近微软官方在一篇技术文章中,说明了其实这是现代浏览器采用了多线程的架构所建构。简单而言,当你运行一个浏览器的时候,这个浏览器其实并非是单进程软件,而是采用了多进程的架构,浏览器在运行的时候,会调动不同的资源,但是在任务管理器的后台上,都会显示为浏览器的图标,这就是浏览器为什么运行后会有多个后台进程的真正原因。

微软详细解释了自家Edge浏览器的多进程架构,同样的原理也适用于目前世界第一大浏览器谷歌的Chrome浏览器上。微软表示,浏览器采用多进程架构,浏览器在工作时主要被分为几个不同的行程。

首先是浏览,这是主要的进程,负责视窗窗口和选项管理,控制浏览器的地址栏、前进/ 后退按钮等框架、且要处理网络请求和档案存取。

其次是计算,通过执行网站提供的程式码,来控制一个网页的呈现,能够处理超文字标记语言(HTML)、级联样式表(CSS)、JavaScript 和图像等内容。

然后是GPU硬件加速的计算,这部分负责与图形硬体相关的所有任务,比如加速图形运算、并将处理器结果输出到显示器上。此外还有实用功能的进程,这部分负责了影片播放、网络服务、资料解码、以及集合管理,微软和谷歌的浏览器可借此控制、管理、协调系统资源。

此外进程中还有附加程式,这部分负责了对各个附加程式的管理,每个进程的资源使用情况、以及同主进程/计算进程的沟通。最后还有崩溃处理的进程,如果浏览器发生崩溃,Crashpad Handler 能够捕获异常、并将错误报告传递,以查找问题和修复故障。

必须要说的是,出于可靠性和安全性的考虑,即便是同一网页上的不同元素,也可能被分配了单独的进程。这样,即使是不慎被恶意软体利用了一个计算进程中的安全漏洞,也可避免其影响另一个行程。

所以综合来讲,浏览器虽然只是单独的一个软件,但要正常使用浏览器,那么就需要电脑分配多个进程给它,甚至有的时候在一些复杂的网页上,电脑的计算要耗费不少的性能,所以还会导致浏览器的占用率比较高,比如说一些可播放视频的网站。这也是为什么我们在后台看到一个浏览器会有这么多进程的原因。

从好处上来看,多进程的浏览器提升了整体的安全性,防止了不同功能在同一个进程中的串访,而且即使出现了一些故障,比如说网页崩溃,也只会影响其中一个进程,对浏览器的稳定性也有很大的重要。

通过这个释疑,以后大家打开浏览器如果再看到这么多的后台进程,大家也就不用担心了,这是浏览器努力为大家服务的表现,而且在大多数时候后台进程虽多,但是处理器资源占用并不高,除非你玩什么网页游戏或者通过网页观看视频!

产服务内存高问题

问题描述#

  • 1、“计算中心” 服务堆内存分配4g,在生产环境运行一段时间后,实际占用内存4.8G,业务运行正常,未出现OOM。(本文以此服务进行排查)
  • 2、生产环境的老项目,均出现运行一段时间后,内存被占满但未OOM的情况。部分实例因内存占用过高导致被系统kill,一般需要通过增加机器、实例进行解决(资源浪费)。

造成的影响#

  • 1、服务器物理内存15g,部署了三个服务。如实际占用内存都超过4.8g,导致服务器物理内存不够用,出现告警而将占用内存最大进程kill掉,影响生产服务的可用性,后果十分严重。
  • 2、如服务申请的内存超出了JVM能提供的内存大小(内存泄漏),将会导致java堆内存溢出,从而发生full gc,导致服务响应大幅度变慢,卡机等状态。
  • 3、在公司大促等场景的情况下,内存占用很高的服务会带来很大风险,通常需提前联系运维同事对“计算中心”进行重启,增加了开发及运维同事维护的工作量。

排查过程

代码#

(1)根据cat监控,获取“计算中心”中的热点方法,进行REVIEW,修正了部分可能会导致内存泄露的方法。并进行了观察。

(2)通过VisualVM监控,定位到部分耗时较久的操作DB热点方法,通过增加索引等方式,把查询性能控制在毫秒级。

(3)dump“计算中心”的内存镜像,通过MAT等工具观察各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系。

结论:通过以上三点,未解决和定位“计算中心”内存高问题。由此可以认为,“计算中心”的内存占用问题与代码无关。

系统#

通过java ps| aux java 查看,“计算中心”服务实际占用的内存在4.9G左右,超过了JVM堆内存设置的大小但并未出现OOM,业务正常运行。通过free -g命令,可以发现buff/cache,3个g左右。centos中内存的分配是buff/cache + free + used=物理内存大小,系统分配给临时文件系统的大小默认是用掉一半的物理内存,这样会造成buff/cache很大,而free很小。最终结论可能为服务内存没有释放使用了buff/cache。导致服务内存占用很高。

结论:和SRE沟通实际重启服务后,内存使用率立刻降低,但是buff/cache的大小没有变化。由此可以认为,“计算中心”的内存占用问题与系统缓存无关。

JVM#

1、通过VisualVM监控生产环境computing内存使用情况得出,在服务内存占用4.8g的情况下,堆内存(新生代 + 老年代)正常GC,在增长到2g左右会GC到300~500m,Matespace仅使用了120m左右。检查了生产JVM参数。项目启动参数没有配置:-XX:MaxDirectMemorySize,来指定最大的堆外内存大小。这个阈值不配置的话,默认占用-Xmx相同的内存。在堆内内存正常的情况下,怀疑是堆外内存占用了大部分内存,导致服务内存占用很高。

结论:和SRE沟通,在生产环境找了两台计算中心服务实例配置 -XX:MaxDirectMemorySize 参数后实际观察后,仍未解决“计算中心”内存高问题。由此可以认为,“计算中心”的内存占用问题与堆外内存无关。

2、在发现-XX:MaxDirectMemorySize 指定堆外内存大小的参数没有配置后。我检查了“计算中心”服务的启动参数并且和之前生产环境的服务进行了对比,发现了以下问题。


1)生产及测试环境JVM参数配置混乱,同一应用不同实例多套启动参数配置。
2)服务启动参数,未区分JDK版本。如:JDK1.7、JDK1.8参数混用。
3)生产服务根据模板部署,导致必要JVM参数未配置,部分参数配置不需要、不合理。
4)不同类型的应用,采用统一的启动参数配置,不具有针对性。在以上问题的基础上,基于目前生产环境各项目统一使用的"CMS垃圾回收器"进行参数调整。针对计算中心的JDK版本(1.8),出了一套JVM配置方案。并在生产服务器调整后重启观察。


结论:“计算中心”生产环境服务,在运行一段时间后,仍出现内存占用高问题。由此可以认为,“计算中心”的内存占用问题与不同JDK版本的参数混用问题无关。

3、经调研,逐渐被淘汰的垃圾回收器比如ParallelOldGC和CMS,只要JVM申请过的内存,即使发生了GC回收了很多内存空间,JVM也不会把这些内存归还给操作系统。这就会导致top命令中看到的RSS(进程RAM中实际保存的总内存)只会越来越高,而且一般都会超过Xmx的值。JDK1.9以后。默认的垃圾回收器已经选择了G1。

G1相比CMS有更清晰的优势:

1)CMS采用"标记-清理"算法,所以它不能压缩,最终导致内存碎片化问题。而G1采用了复制算法,它通过把对象从若干个Region(独立区域)拷贝到新的Region(独立区域)过程中,执行了压缩处理,垃圾回收后会整合空间,无内存碎片。

2)在G1中,堆是由Region(独立区域)组成的,因此碎片化问题比CMS肯定要少的多。而且,当碎片化出现的时候,它只影响特定的Region(独立区域),而不是影响整个堆中的老年代。

3)而且CMS必须扫描整个堆来确认存活对象,所以,长时间停顿是非常常见的,无法预测停顿时间。而G1的停顿时间取决于收集的Region(独立区域)集合数量,在指定时间内只回收部分价值最大的空间,而不是整个堆的大小,所以相比起CMS,长时间停顿要少很多,可控很多。

4)G1选回收阶段不会产生“浮动垃圾”,由于只回收部分Region(独立区域),所以STW(stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起)时间我们可控,所以不需要与用户线程并发争抢CPU资源。而CMS并发清理需要占据一部分的CPU,会降低吞吐量。G1由于STW,所以不会产生"浮动垃圾",CMS在并发清理阶段会产生的无法回收的垃圾。

因此在以下场景下G1更适合:

1)服务端多核CPU、JVM内存占用较大的应用。

2)应用在运行过程中会产生大量内存碎片、需要经常压缩空间。

3)想要更可控、可预期的GC停顿周期;防止高并发下应用雪崩现象。

结论:将”计算中心“使用的垃圾回收机制升级为G1,并增加G1相关的优化内存的参数,在生产服务器进行观察一周后发现服务内存始终稳定在了3.3G左右,业务处理性能稳定,成功解决了“计算中心”服务占用内存较高的问题,提升了系统的可用性,无需通过增加物理资源来提升服务整体性能。

CMS升级为G1方式

计算中心“生产全部服务实例部署的服务器,使用的是JDK1.8,JDK1.8支持G1垃圾回收器,故将服务启动参数进行统一调整:

1)原参数(主要问题:使用CMS版本,JDK1.7,1.8参数混用,未指定堆外内存大小)

/opt/java/jdk1.8.0_102/bin/java -Dapp.home=${APP_HOME} -Dspring.profiles.active=prd -Dserver.port=${SERVER_PORT} -server -Xms4G -Xmx4G -Xmn2g -Xss256k -XX:PermSize=128m -XX:MaxPermSize=512m -Djava.awt.headless=true -Dfile.encoding=utf-8 -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:AutoBoxCacheMax=20000 -XX:-OmitStackTraceInFastThrow -XX:ErrorFile=${APP_HOME}/logs/hs_err_%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${APP_HOME}/logs/ -Xloggc:${APP_HOME}/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar ${APP_HOME}/webapps/${JAR_NAME} ${SERVER_PORT}"

2)新参数(使用G1做为垃圾回收器)

/opt/java/jdk1.8.0_102/bin/java -Dapp.home=${APP_HOME} -Dspring.profiles.active=prd -Dserver.port=${SERVER_PORT} -server -Xms4g -Xmx4g -Xss256k -XX:NewSize=512m -XX:MaxNewSize=512m -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=40 -XX:G1HeapRegionSize=8m -XX:+ExplicitGCInvokesConcurrent -XX:ParallelGCThreads=4 -Dsun.rmi.dgc.server.gcInterval=36000000-Dsun.rmi.dgc.client.gcInterval=36000000-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=256m -XX:MaxDirectMemorySize=512m -XX:GCTimeRatio=19 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=30 -XX:ErrorFile=${APP_HOME}/logs/hs_err_%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${APP_HOME}/logs/ -Xloggc:${APP_HOME}/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar ${APP_HOME}/webapps/${JAR_NAME} ${SERVER_PORT}"

注:不同服务器环境,不同容器,脚本配置各不相同,要在对应脚本的基础上进行针对性升级。

生产G1回收器主要参数说明

JVM相关概念说明

JDK1.7内存模型#

实际占用内存大小(参数):-XX:MaxPermSize(非堆) + -Xmx(堆) + -Xss(栈) + -XX:MaxDirectMemorySize(堆外)

JDK1.8内存模型#

实际占用内存大小(参数):-XX:MaxMateSpaceSize(堆外) + -Xmx(堆) + -Xss(栈) + -XX:MaxDirectMemorySize(堆外)

GC流程图#

1、什么时候触发Minor GC

2、触发Minor GC 的过程

3、Full GC 的过程

1、新创建的对象一般会被分配在新生代中。常用的新生代的垃圾回收器是 ParNew 垃圾回收器,它按照 8:1:1 将新生代分成 Eden 区,以及两个 Survivor 区。创建的对象将 Eden 区全部挤满,这个对象就是「挤满新生代的最后一个对象」。此时,Minor GC 就触发了。

2、在正式 Minor GC 前,JVM 会先检查新生代中对象,是比老年代中剩余空间大还是小。Minor GC 之后 Survivor 区放不下剩余对象,这些对象就要进入到老年代,所以要提前检查老年代是不是够用。

3、老年代剩余空间大于新生代中的对象大小,那就直接 Minor GC,GC 完 survivor 不够放,老年代也绝对够放。老年代剩余空间小于新生代中的对象大小,这时候就要进入老年代空间分配担保规则。

4、老年代空间分配担保规则:如果老年代中剩余空间大小,大于历次 Minor GC 之后剩余对象的大小,那就允许进行 Minor GC。因为从概率上来说,以前的放的下,这次的也应该放的下。那就有两种情况:

  • 老年代中剩余空间大小,大于历次 Minor GC 之后剩余对象的大小,进行 Minor GC
  • 老年代中剩余空间大小,小于历次 Minor GC 之后剩余对象的大小,进行 Full GC,把老年代空出来再检查。
  • 结合第四步,开启老年代空间分配担保规则只能说是大概率上来说,Minor GC 剩余后的对象够放到老年代,如果放不下:Minor GC 后会有这样三种情况:
  • Minor GC 之后的对象足够放到 Survivor 区,GC 结束。
  • Minor GC 之后的对象不够放到 Survivor 区,接着进入到老年代,老年代能放下,那也可以,GC 结束。
  • Minor GC 之后的对象不够放到 Survivor 区,老年代也放不下,那就只能 Full GC。
  • 以上是成功 GC 的例子,以下3 中情况,会导致 GC 失败,报 OOM:

紧接上一节 Full GC 之后,老年代任然放不下剩余对象,就只能 OOM。未开启老年代分配担保机制,且一次 Full GC 后,老年代任然放不下剩余对象,也只能 OOM。开启老年代分配担保机制,但是担保不通过,一次 Full GC 后,老年代任然放不下剩余对象,也是能 OOM。注:

  • 老年代分配担保机制在JDK1.5以及之前版本中默认是关闭的,需要通过HandlePromotionFailure手动指定,JDK1.6之后就默认开启。如果我们生产环境服务使用的是JDK/1.7JDK1.8,所以不用再手动去开启担保机制。
  • Full GC主要指新生代、老年代、metaspace上的全部GC。

感谢以下作者给与我的帮助#

  • 图解GC流程:https://www.cnblogs.com/shuiyj/p/12640692.html
  • CMS垃圾回收升级G1回收器实践:http://arick.net/content/44
  • JAVA常见问题分析:https://blog.51cto.com/hmtk520/2067043

作者: zhfeat

出处:https://www.cnblogs.com/zhfeat/p/13261543.html