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://www.jianshu.com/p/355ee06c3d2b


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM