JAVA运维总结篇

写这篇文章主要目的是完成自己多年来运维JAVA应用的一个总结,相当于个人知识库,以后工作中遇到问题便于临时查阅并不断完善自己的知识体系。

上图,就知道Tomcat在JAVA容器界是多么重要。

Tomcat是一个开箱即用的软件,配置java环境变量即可把Tomcat进程运行起来,但要投入生产环境,有哪些需要注意的呢?

(1)、性能,默认的Tomcat配置可以正常提供服务,但对于高负载的应用就相当吃力。

  1. 调JVM

    • 调整为server模式,默认为client模式,针对生产环境有做优化,启动速度慢,运行速度快(官方说的);
    • 为了减少JVM垃圾回收和重新分配内存的频率可以把Xms和Xmx设置同样的值,从而tomcat提供更多的服务;
    • JVM有几种垃圾回收算法:【阅读一篇文章:建议开发不要主动去调用System.gc(),这会导致stop-the-world,让JVM自己去解决垃圾回收吧】
      • 垃圾标识算法:引用计数法、根搜索算法;
      • 垃圾收集算法:标记-清除算法,复制算法,标记-整理算法,分代收集算法(Generational Garbage Collection);
      • 垃圾收集器对比与应用场景:


    • 进程启动参数选择【可以进入网站自助生成配置:http://jvmmemory.com/
    • 总结GC 调优目标基本有三个思路:
      • 降低 GC 频率,可以通过增大堆空间,减少不必要对象生成;
      • 降低 GC 暂停时间,可以通过减少堆空间,使用 CMS GC 算法实现;
      • 避免 Full GC,调整 CMS 触发比例,避免 Promotion Failure 和 Concurrent mode failure(老年代分配更多空间,增加 GC 线程数加快回收速度),减少大对象生成等。
  2. 配置连接器(有三种连接器供选择)

    • BIO全称blocking I/O,配置参数
      protocol=”HTTP/1.1”
    • NIO全称Non-blocking I/O,配置
      protocol=”org.apache.coyote.http11.Http11NioProtocol”
    • APR全称Apache Portable Runtime,配置
      protocol=”org.apache.coyote.http11.Http11AprProtocol”
    • 下面是三者之间对比:


    • 配置模版:


(2)、性能监控

推荐使用JavaMelody 能够监测Java或Java EE应用程序服务器,并以图表的方式显示:Java内存和Java CPU使用情况,用户Session数量,JDBC连接数, 和http请求、sql请求、jsp页面与业务接口方法(EJB3、Spring、 Guice)的执行数量,平均执行时间,错误百分比等。图表可以按天,周,月,年或自定义时间段查看。

  1. 下载地址:
    https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/javamelody/javamelody-1.48.0.jar

  2. 配置web.xml:

       <filter>  
             <filter-name>monitoring</filter-name>  
                <filter-class>net.bull.javamelody.MonitoringFilter</filter-class>  
        </filter>  
        <filter-mapping>  
                <filter-name>monitoring</filter-name>  
                <url-pattern>/*</url-pattern>  
        </filter-mapping>  
        <listener>  
                <listener-class>net.bull.javamelody.SessionListener</listener-class>  
        </listener>
  1. 重启Tomcat应用,访问地址:
    http://host/context/monitoring

(3)、高可用

  • Tomcat的高可用官方目前是3种方案:

    • Session持久化并把session保存在共享存储;
    • Session持久化并把session保存的共享数据库(JDBC连接);
    • 通过SimpleTcpCluster ,每个tomcat节点都保存所有tomcat节点的数据,这个也是集群模式的基础;
    • 另外,第三方有支持redis共享session从而实现高可用,比较推荐,但是模块稳定性可能需要考虑下。
  • 官方给的集群方案。


  • 高可用涉及面比较广,需要根据自己业务情况设计对应的方案,推荐两个链接可以详细研究:
    https://tomcat.apache.org/tomcat-8.0-doc/cluster-howto.html
    https://segmentfault.com/a/1190000009591087

(4)、安全

  1. 移除容器版本信息,黑客很容易根据容器版本号找到对应的漏掉做针对性的攻击;
    修改文件server.xml,如下
<Connector port="8080" protocol="HTTP/1.1"  connectionTimeout="20000" Server =" "
redirectPort="8443" />
  1. 安全启动进程,试想有人在请求中加<% System.exit(1); %>,后果是很严重的。
    官方建议tomcat正确启动姿势,
    ./startup.sh -security
    参考链接:https://tomcat.apache.org/tomcat-6.0-doc/security-manager-howto.html

  2. 推荐使用HTTPS协议,如果tomcat直接对外访问就加一个HTTPS吧,如果前端有负载均衡器,负载均衡器使用HTTPS,tomcat放在一个安全的内网使用http也可;

  3. 为Cookie设置HttpOnly属性


  4. 推荐tomcat启动使用单独的普通用户,避免黑客攻击后导致整个服务器沦陷;

  5. 在部署生产环境时,去除tomcat默认的应用和页面,避免存在安全风险,删除$tomcat/webapps目录下所有文件即可;

  6. 改变Tomcat的shutdown端口和命令,假如默认的8005端口对外网访问,可以直接通过远程将运行的tomcat关闭,很危险,建议修改server.xml
    <Server port="8867" shutdown="NOTGONNAGUESS">

  7. 替换默认的404,403,500页面,和避免异常报错暴露在页面
    在web.xml文件下添加到</web-app>之前

<error-page>
   <error-code>404</error-code>
   <location>/error.jsp</location>
</error-page>
<error-page>
   <error-code>403</error-code>
   <location>/error.jsp</location>
</error-page>
<error-page>
   <error-code>500</error-code>
   <location>/error.jsp</location>
</error-page>
<error-page>
   <exception-type>java.lang.Exception</exception-type>
   <location>/error.jsp</location>
</error-page>

(5)、线程dump

当我们的java应用比我们预期的要慢的时候,我们就需要用到thread dumps,然后分析它们并知道他们的瓶颈或阻塞的线程等信息,然后针对性的优化从而提示整个系统的性能。

  1. 首先我们了解2个概念;

    • Thread contention(线程竞争):线程竞争是一个状态,等待锁被释放,这个锁正好被其他线程占用。在web网站中,不同的线程频繁的访问共享资源。比如记录日志,线程要记录日志必须要获得锁然后才能记录日志。
    • Deadlock(死锁):死锁是一种特殊的线程竞争,2个或者更多的线程为了完成自己的任务必须等待其他线程完成他们的任务。比较典型案例,如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象。
  2. 了解java线程背景信息

    • 线程同步:
      为了解决同时访问资源,一个线程需要在访问共享资源时使用线程同步。Java中使用monitor作为线程同步,每个对象都有一个monitor,一个monitor只能被一个线程拥有。假如其他线程获得这个monitor需要进入等待队列,等待释放;

    • 线程状态:

      • NEW:线程刚刚启动还没有开始处理任务;
      • RUNNABLE:线程正在占用CPU并且处理任务;
      • BLOCKED:线程是阻塞的,等待获取monitor,一般是等待共享对象、资源;
      • WAITING:线程无限时间等待另外一个线程,为了执行特定的任务;
      • TIMED_WAITING:线程有限时间等待另外一个线程,为了执行特定的任务;
      • TERMINATED:线程已经结束生命;
    • 线程类型:

      • daemon thread:守护线程,
      • non-daemon threads:非守护线程
  3. 获取Java堆栈

jps -v #获取java进程PID
jstack -F 31336 > dump.log #强制dump出线程堆栈(不同版本,获取方式不一样)

【注】:线程堆栈是某一时刻的堆栈快照,为了分析线程状态改变,需要提取5-10次,每5秒dump一次。

  1. 具体的线程分析内容比较多,可以参考下面链接:
    https://dzone.com/articles/how-analyze-java-thread-dumps
    https://dzone.com/articles/how-to-read-a-thread-dump

(6)、JVM dump

Head dump是JVM某个时刻的内存快照,可以帮助我们分析内存泄露和分析java应用的内存使用情况。Heap dump通常市存储2进程hprof文件,我们打开和分析需要用jhat 或者JVisualVM等其他工具。

  1. 获取Heap dump
    jmap -F -dump:live,format=b,file=/tmp/dump.hprof 12587 #dump时间比较长
  2. 查看heap dump 【不建议在生产环境分析,建议在本地找一台内存大的机器启动】
    jhat /tmp/dump.hprof 12587
  3. 访问:http://ip:7000/
  4. 具体分析内容比较多,给两个链接详细研究。
    https://www.baeldung.com/java-heap-dump-capture
    https://www.javatang.com/archives/2017/10/30/53562102.html

(7)、GC日志

GC叫做垃圾收集,正常的垃圾回收是对整个JVM健康起着重要作用,如果回收不及时,会导致GC频繁,GC时间过长,严重情况可能导致OOM,严重影响业务正常。下面介绍怎么开启gc日志,命令行查看gc,常用gc的含义。

  • 开启gc日志
-XX:+PrintGCDetails -Xloggc:/opt/tmp/myapp-gc.log         #这个支持java 8
-Xlog:gc*:file=/opt/tmp/myapp-gc.log                                  #这个支持java 9
gclog-analysis

有下面的参数适合于java 8可以选择性开启:

-XX:+DisableExplicitGC                             #开发想自己调用垃圾回收,在生产环境中不建议开发调用:System.gc() or Runtime.getRuntime().gc()
-XX:+PrintGCDetails                                 #默认是禁用的,可以打印更加详细的垃圾回收信息
-XX:+PrintGCApplicationStoppedTime     #默认是禁用的,这个选项代表在GC过程中,应用pause时间
-XX:+PrintGCApplicationConcurrentTime #默认是禁用的,这个选项代表在GC过程中,应用running时间
-XX:+PrintGCDateStamps                         #打印每个gc的日期和时间
-Xloggc:gclog.log                                       #gclog.log是gc日志的具体路径,所有gc日志记录在这个文件
-XX:+UseGCLogFileRotation                    #假如gc日志达到指定的大小,会开启自动轮换
-XX:NumberOfGCLogFiles=5                   #默认是1,轮换日志的数目
-XX:GCLogFileSize=2000k                      #指定gc日志的大小,当达到这个大小后会轮换一次
  • 命令行开启gc
jps -v #获取java进程PID
jstat –gc  PID 1000      #PID是jvm的进程号

输出内容解释:
S0C #显示当前Survivor 0区的大小
S1C #显示当前Survivor 1区的大小
S0U #显示当前使用Survivor 0区的大小
S1U #显示当前使用Survivor 1区的大小
EC #显示E区的大小
EU #显示已使用E区的大小
OC #显示old区的大小
OU #显示已经使用的old区
PC #显示permanent区的大小
PU #显示已经使用的permanent区大小
YGC #young区发生gc的次数
YGCT #在young区累计的时间
FGC #full gc发生的次数
FGCT #full gc累计占有时间
GCT #gc累计消耗时间

详细的可以见下面:
https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html

(8)、java实用命令【java命令集很强大】

  • java:启动java应用,引导main()方法;
  • jps:主要是列出目标机器上运行的JVM;
  • jstat:列出JVM性能统计数据;
  • jstack:打印指定进程的java堆栈信息;
  • jcmd:发送一些诊断命令给运行的JVM;
  • jmap: 打印指定进程、核心文件或远程调试服务器的共享对象内存映射或堆内存细节。
  • jhat:命令行工具解析Heap dump文件并启动一个web服务;
  • jdb:针对java class,简单的命令行debug工具;
  • jinfo:打印指定java进程的配置信息;
  • keytool:是一个密钥和证书的管理工具,java使用https需要用到;
  • jar:主要是给java应用的打包和解压工具;
  • javac:将java源码编译为二进制class文件;
  • jconsole:开启一个图形界面,让你监控和管理java应用;
  • jvisualvm:很好的heap dump分析工具;

参考文献

https://geekflare.com/apache-tomcat-hardening-and-security-guide/
https://stackify.com/tomcat-performance-monitoring/
https://tomcat.apache.org/articles/performance.pdf
http://www.infoq.com/cn/articles/Troubleshooting-Java-Memory-Issues
https://plumbr.io/handbook/garbage-collection-algorithms-implementations
https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/index.html
https://crowhawk.github.io/2017/08/15/jvm_3/
http://www.tecbar.net/optimize-tomcat-performance/
http://www.agileload.com/agileload/blog/2013/06/20/performance-improvement-strategies-for-tomcat-server
https://geekflare.com/apache-tomcat-hardening-and-security-guide/
https://dzone.com/articles/how-analyze-java-thread-dumps
https://tomcat.apache.org/tomcat-8.0-doc/cluster-howto.html
https://hk.saowen.com/a/ed3d22c03507a3addef218c6d2fe69991d48799d3f9b9088ea47bcaa5ee4fb09
https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html
https://dzone.com/articles/enabling-and-analysing-the-garbage-collection-log
https://dzone.com/articles/what-is-garbage-collection-log-how-to-enable-ampnb
https://dzone.com/articles/how-monitor-java-garbage

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,230评论 11 349
  • 每天三件事71/100天 1、完成基础日常,还差最高14个, 说好的,要做就做就做最好,头部效益,但是怎么做都发现...
    钱程浩瀚阅读 82评论 0 0
  • 六十三章 玄界的聘礼,很是厚重。作为太晨宫长公主,什么没有见过,所以这玄界的第一道聘礼,便是“中宫皇后”。这在情理...
    墨冉_诺诺阅读 1,307评论 0 11
  • 我目送过很多场的离别。 初中时候送好朋友去读技校,下雨,我们在车旁给她唱童话,给她写信,抱着她嚎啕大哭,那时候啊,...
    一昂一昂阅读 1,047评论 0 3