日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

在生产中运行Java:SRE的观点

發布時間:2023/12/3 java 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在生产中运行Java:SRE的观点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作為站點可靠性工程師 (SRE),我確保我們的生產服務高效,可擴展且可靠。 典型的SRE是生產大師,必須對更廣泛的體系結構有很好的了解,并精通許多更精細的細節。

SRE是會說多種語言的程序員,這是很常見的,他們希望能夠理解多種不同的語言。 例如,C ++可能很難編寫,測試和正確使用,但具有高性能,非常適合諸如數據庫之類的后端系統。 Python很容易編寫,非常適合快速編寫腳本,對自動化很有用。 Java位于中間位置,盡管它是一種編譯語言,但它提供了類型安全性,性能以及許多其他優點,使其成為編寫Web基礎結構的理想選擇。

盡管SRE采用的許多最佳實踐可以推廣到任何語言,但是Java還是存在一些獨特的挑戰。 本文計劃重點介紹其中一些,并討論我們可以采取哪些措施來解決這些問題。

部署方式

一個典型的Java應用程序由數百個類文件組成,這些類文件由您的團隊編寫,或者由應用程序依賴的通用庫編寫。 為了控制類文件的數量,并提供更好的版本控制和分隔,通常將它們捆綁到JAR或WAR文件中。

托管Java應用程序的方法有很多,一種流行的方法是使用Java Servlet容器,例如Tomcat或JBoss 。 從理論上講,它們提供了一些通用的Web基礎結構和庫,以使其更易于部署和管理Java應用程序。 以Tomcat(一個提供實際Web服務器并代表您加載應用程序的Java程序)為例。 這在某些情況下可能會很好地起作用,但實際上會增加額外的復雜性。 例如,您現在需要跟蹤JRE版本,Tomcat版本和應用程序版本。 測試不兼容性,并確保每個人都使用相同版本的完整堆棧可能會出現問題,并導致細微的問題。 Tomcat還帶來了自己的定制配置,這是另一回事。

一個很好的承租人是“ 保持簡單 ”,但是在Servlet容器方法中,您必須跟蹤幾十個Tomcat文件,一個或多個組成應用程序的WAR文件以及所有的Tomcat配置。隨之而來。

因此,有些框架通過嵌入自己的Web服務器,而不是托管在完整的應用程序服務器中,試圖減少這種開銷。 仍然有一個JVM,但它會調用一個JAR文件,其中包含運行該應用程序所需的所有內容。 支持這些獨立應用程序的流行框架是Dropwizard和Spring Boot 。 要部署該應用程序的新版本,只需更改一個文件,然后重新啟動JVM。 這在開發和測試應用程序時也很有用,因為每個人都在使用相同版本的堆棧。 對于回滾(SRE的核心工具之一)來說,它也特別有用,因為只需更改一個文件即可(可以快速更改符號鏈接)。

Tomcat樣式的WAR文件要注意的一件事是,該文件將包含應用程序類文件以及該應用程序依賴于JAR文件的所有庫。 在獨立方法中,所有依賴項都合并到單個Fat JAR中 。 單個JAR文件,其中包含整個應用程序的類文件。 這些Fat或Uber JAR不僅易于版本化和復制(因為它是單個不可變文件),而且由于對依賴項中未使用的類進行修剪而實際上可以小于等效的WAR文件。

通過不需要單獨的JVM和JAR文件,甚至可以更進一步。 實際上,例如capsule.io之類的工具可以將JAR文件,JVM和所有配置捆綁到一個可執行文件中。 現在,我們可以真正確保整個堆棧都使用相同的版本,并且部署與服務器上可能已經安裝的內容無關。

保持簡單,并使用單個Fat JAR或可能的可執行文件,使應用程序的版本快速便捷。

啟動

即使Java是一種編譯語言,它也不會編譯為機器代碼,而是會編譯為字節碼。 在運行時,Java虛擬機(JVM)解釋字節碼,并以最有效的方式執行它。 例如, 即時 (JIT)編譯使JVM可以監視應用程序的使用方式,并即時將字節碼編譯為最佳機器代碼。 從長遠來看,這對應用程序可能是有利的,但是在啟動過程中,它可能會使應用程序在數十分鐘或更長時間內處于次優狀態。 需要注意的是,這對負載平衡,監視,容量規劃等有影響。

在多服務器部署中,最佳實踐是將流量緩慢增加到新啟動的任務,使其有時間進行預熱,并且不損害服務的整體性能。 在將新任務放入用戶服務路徑之前,您可能會通過向其發送人工流量來預熱新任務。 如果預熱過程無法逼近正常的用戶流量,則人工流量可能會出現問題。 實際上,這種偽造的流量可能會觸發JIT對通常不會發生的情況進行優化,從而使應用程序處于未達到最佳狀態或處于比未進行JIT時更糟糕的狀態。

容量規劃時也應考慮啟動緩慢。 不要期望冷任務與熱任務處理相同的負載。 推出新版本的應用程序時,這一點很重要,因為系統的容量會下降,直到任務預熱。 如果不考慮這一點,可能會同時重新加載太多任務,從而導致基于容量的級聯中斷。

期待冷啟動,并嘗試以實際流量預熱應用程序。

監控方式

該建議是通用的監視建議 ,但是對于Java值得重復。 確保從Java應用程序導出最重要和最有用的度量標準,并對其進行收集并輕松繪制圖形。 有許多工具和框架可用于導出指標,甚至還有更多的工具和框架可用于收集,匯總和顯示。

當出現問題時,應該僅從收集的指標中排除故障即可 。 您不應該依賴日志文件或查看代碼來處理中斷。

大多數中斷是由更改引起的。 也就是說,應用程序的新版本,配置更改,新的流量來源,硬件故障或后端依賴關系的行為不同。 應用程序導出的度量標準應包括識別Java版本,應用程序和使用中的配置的方法。 它應該分解流量,混合,錯誤計數等的來源。還應該跟蹤后端依賴項的運行狀況,延遲,錯誤率等。 在大多數情況下,這足以快速診斷出故障。

特定于Java的指標可以幫助您了解應用程序的運行狀況和性能。 指導有關如何擴展和優化應用程序的未來決策。 垃圾回收時間,堆大小,線程數,JIT時間都很重要,并且特定于Java。

最后,關于測量響應時間或等待時間的注釋。 也就是說,應用程序處理請求所花費的時間。 許多人會誤以為平均等待時間,部分原因是它很容易計算。 平均值可能會引起誤解 ,因為它沒有顯示分布的形狀 。 大多數請求可能會很快得到處理,但請求的尾部可能很少,但需要一段時間。 這對于JVM應用程序尤其令人不安,因為在垃圾回收過程中,有一個“ 停止世界” (STW)階段,在此階段,應用程序必須暫停以允許垃圾回收完成。 在此暫停中,不會響應任何請求,并且用戶可能要等待幾秒鐘。

最好收集最大或99%(或更高)的百分比延遲。 對于百分位數,也就是說,每100個請求中,有99個的送達速度快于該數字。 查看最壞情況下的延遲更有意義,并且更能反映用戶感知的性能。

衡量重要的指標,以后可以依靠。

內存管理

您花費大量時間來學習各種JVM垃圾收集算法 。 當前的最新狀態是并發收集器G1或CMS 。 您可以決定哪種方法最適合您的應用程序,但目前G1可能是贏家。 有很多很棒的文章解釋了它們的工作方式,但我將介紹一些關鍵主題。

啟動時,Java虛擬機(JVM)通常會保留大量OS內存,并將其分為堆和非堆。 非堆包含諸如Metaspace ( 正式稱為Permgen )和堆棧空間之類的區域。 元空間用于類定義,而堆棧空間用于每個線程的堆棧。 堆用于創建的對象,這些對象通常占用大部分內存使用量。 與典型的可執行文件不同,JVM具有-Xms和-Xmx標志 ,用于控制堆的最小和最大大小。 這些限制限制了JVM將使用的最大RAM量,這可以使服務器上的內存需求可預測。 通常將這兩個標志設置為相同的值,以提供它們以填充服務器上的可用RAM。 還有一些針對Docker容器調整大小的最佳實踐。

垃圾回收(GC)是通過查找不再使用(即不再引用)且可以回收的Java對象來管理此堆的過程。 在大多數情況下,JVM會掃描對象的完整圖,并標記找到的對象。 最后,將所有未訪問的內容刪除。 為了確保沒有競爭狀況,GC通常必須停止運行(STW),這會在應用程序完成時將其暫停一會兒。

GC是(可能是不必要的)怨恨的根源,因為它被歸咎于許多性能問題。 通常,這歸結為不了解GC的工作原理。 例如,如果堆的大小太小,則JVM可以主動進行垃圾收集,從而徒勞地釋放空間。 然后,應用程序可能會陷入“ GC崩潰 ”循環中,這在釋放空間方面幾乎沒有進展,并且在GC中花費了越來越多的時間,而不是運行應用程序代碼。

可能發生這種情況的兩種常見情況是內存泄漏或資源耗盡 。 垃圾收集的語言不應允許通常所說的內存泄漏,但是,它們可能會發生。 例如,維護一個永不過期的對象的緩存。 此緩存將永遠增長,即使該緩存中的對象可能永遠不會再使用,它??們仍然被引用,因此不適合進行垃圾回收。

另一個常見的情況是無限隊列 。 如果您的應用程序將傳入的請求放置在無限制的隊列中,則該隊列可能永遠增長。 如果請求數量激增,保留在隊列中的對象可能會增加堆使用率,從而導致應用程序在GC中花費越來越多的時間。 因此,應用程序將有更少的時間來處理來自隊列的請求,從而導致積壓量增加。 隨著GC努力尋找任何要釋放的對象,這逐漸失去控制,直到應用程序無法取得任何進展。

另外一個細節是,垃圾收集器算法具有許多優化措施,可以嘗試減少總的GC時間。 一個重要的發現( 弱代假設 )是對象要么存在很短時間(例如,與處理請求有關),要么存在很長時間(例如,管理壽命長的資源的全局對象)。

因此,堆進一步劃分為年輕空間和舊空間。 在年輕空間中運行的GC算法假定對象將被釋放,否則,GC會將對象提升到舊空間。 用于舊空間的算法做出了相反的假設,即對象不會被釋放。 因此,也可以調整年輕人/老年人的大小,并且根據G1或CMS,方法將有所不同。 但是,如果年輕空間太小,那么應該只存在很短時間的物體最終將被提升到舊空間。 打破了舊的GC算法所做的某些假設,導致GC的運行效率降低,并導致了諸如內存碎片之類的次要問題。

如前所述,GC是長尾延遲的來源,因此應關閉監視。 應該記錄GC每個階段所花費的時間,以及GC運行之前和之后堆空間的滿度(按年輕/舊/等等分解)。 這提供了調優或改進應用程序以控制GC所需的所有提示。

讓GC成為您的朋友。 應該特別注意堆和垃圾收集器,并且應該對其進行調整(甚至是粗略地調整),以確保即使在滿載/最壞的情況下也有足夠的堆空間。

其他技巧

調試

Java有許多豐富的工具可用于在開發和生產過程中進行調試。 例如,可以捕獲正在運行的應用程序中的實時堆棧跟蹤和堆轉儲。 這對于了解內存泄漏或死鎖很有用。 但是,通常必須確保應用程序已啟動以允許這些功能,并且典型工具jmap , jcmd等在服務器上實際可用。 在Docker容器或非標準環境中運行應用程序可能會使此操作更加困難,因此請測試并編寫一本有關如何執行此操作的手冊。

許多框架還通過Web服務公開了許多此類信息,以便于調試,例如Dropwizard / threads資源或Spring Boot生產端點 。

不要等到出現生產問題后,立即測試如何獲取堆轉儲和堆棧跟蹤。

更少但更大的任務

JVM的許多功能對每個運行的JVM都有固定的成本,例如JIT和垃圾回收。 您的應用程序也可能具有固定的開銷,例如資源輪詢(后端數據庫連接)等。如果運行較少但較大的實例(就CPU和RAM而言),則可以減少此固定成本,從而實現規模經濟。 我已經看到Java應用程序擁有的CPU和RAM數量增加了一倍,使它每秒能夠處理4倍的請求(不影響延遲)。 但是,這對應用程序以多線程方式進行擴展的能力做出了一些假設,但是通常垂直擴展比水平擴展容易。

使您的JVM盡可能大。

32位和64位Java

如果您的應用程序使用的RAM不超過4GiB,則通常會運行32位JVM。 這是因為32位指針的大小是64位大小的一半,這減少了每個Java對象的開銷。 但是,由于現代CPU是64位的,通常具有64位特定的性能改進,并且RAM的價格便宜,這使得64位JVM無疑是贏家。

使用64位JVM。

減載

還是一般性建議,但對Java很重要。 為避免 GC崩潰或任務繁重而導致過載 ,應用程序應積極減少負載。 也就是說,超出某個閾值,應用程序應拒絕新請求。 盡早拒絕某些請求似乎很糟糕,但是比允許應用程序變得不可恢復并導致所有請求失敗都更好。 有許多避免過載的方法,但是常見的方法是確保隊列有界,并且線程池的大小正確 。 此外,出站請求應該有適當的截止日期 ,以確保緩慢的后端不會對您的應用程序造成問題。

盡可能多地處理請求,而不再處理。

結論

希望本文使您考慮一下Java生產環境。 盡管不是說明性的,但我們重點介紹了一些重點領域。 整個鏈接都應指導您正確的方向。

如果您有任何疑問或意見,請通過@TheBramp與我聯系,或訪問我的網站和博客bramp.net了解更多文章。

翻譯自: https://www.javacodegeeks.com/2017/12/running-java-production-sres-perspective.html

總結

以上是生活随笔為你收集整理的在生产中运行Java:SRE的观点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。