在整體應用架構中,非生產環境情況下,一般 1GB 或者 2GB 的 RAM 就足夠了。如果我們將這個應用程式劃分為 20 或 30 個獨立的微服務,那麼很難期望 RAM 仍將保持在 1GB 或 2GB 左右。特別是如果我們使用 Spring Cloud 的時候。 首先,準備三個服務,Eureka 服 ...
在整體應用架構中,非生產環境情況下,一般 1GB 或者 2GB 的 RAM 就足夠了。如果我們將這個應用程式劃分為 20 或 30 個獨立的微服務,那麼很難期望 RAM 仍將保持在 1GB 或 2GB 左右。特別是如果我們使用 Spring Cloud 的時候。
首先,準備三個服務,Eureka 服務 + 提供 REST API 的兩個簡單的微服務,並將微服務註冊到 Eureka。此處,不以任何方式限制這些應用程式的記憶體使用。
提示:Spring Cloud 簡單應用的搭建示例:https://www.ictgu.cn/share/6644e468
就像你在下圖看到的一樣,三個微服務大概占用了電腦 1.5GB 的 RAM 記憶體。這三個服務是最簡單的應用程式,基本沒有數據處理量,對於這樣的記憶體消耗量,顯然是不理想的。RAM 的最低使用量是用於 Eureka
發現服務,最大的用於初始化聲明式客戶端以調用其他服務的 API。
關於記憶體使用量如下圖 JProfiler 製作的圖表。如圖所示,記憶體使用受堆影響,與非堆相比,它占用了大量空間。
當然,第一個明顯的問題是我們是否需要在堆上運行我們的微服務應用程式的空間。答案是否定的,我們沒有。現在,我們來簡要介紹一下在
Java 8 中如何進行記憶體管理過程。
我們可以將JVM記憶體分為兩個不同的部分:堆(Heap)、 非堆(Non-Heap)。如上圖所示,我們的微伺服器的大小為大小(〜600MB)。反過來,JVM 記憶體 由 年輕代(Young Generation) 、老年代(Old Generation)組成。所有新創建的對象都位於年輕代中。當年輕代被填滿時,執行次要垃圾收集(Minor GC)。更準確的說,這些位於年輕代的一部分對象成為 Eden Space。Minor GC將所有仍然使用的對象從 Eden Space 移動到 Survivor 0。對於Survivor 0 和 Survivor 1 空間執行相同的過程。在 GC 的許多迴圈中幸存的所有對象都被移動到老年代記憶體空間。從哪裡移除對象是由 Major GC 負責的。為了更好地瞭解下圖,在運行 java -jar 命令時,可以使用以下參數設置 Java Heap 的記憶體限制:
- -Xms – JVM啟動時的初始堆大小
- -Xmx – 最大堆大小
- -Xmn - 年輕代的大小,其餘的空間是老年代
JVM記憶體的第二部分,從我們的角度來看,上圖略顯不重要,它是Non-Heap。 Non-Heap 包括以下部分:
- Thread Stacks :所有運行的線程的空間。可以使用 -Xss 參數設置最大線程大小。
- Metaspace : 它替代了 PermGem(Java 7中是JVM堆的一部分)。在 Metaspace 中,通過應用程式載入所有類和方法。看看Spring Cloud 包含的包數量,我們不會在這裡節省大量的記憶體。可以通過設置 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 參數來管理 Metaspace 大小。
- Code Cache : 這是由 JIT(即時)編譯器編譯為本地代碼的本機代碼(如JNI)或 Java 方法的空間。最大大小設置 -XX:ReservedCodeCacheSize 參數。
- Compressed Class Space : 使用 -XX:CompressedClassSpaceSize 設置為壓縮類空間保留的最大記憶體。
- Direct NIO Buffers
更簡單來說,Heap 是用於對象,Non-Heap 是用於類。可以想像,當我們的應用程式 Non-Heap 大於 Heap 時,我們可以結束這種情況。首先,讓我們用下麵的參數來運行我們的服務發現。在我看來,如果您在 Spring Boot 上啟動具有內嵌 Tomcat 的 Eureka,這些配置是最低的值。
-Xms16m \
-Xmx32m \
-XX:MaxMetaspaceSize=48m \
-XX:CompressedClassSpaceSize=8m \
-Xss256k \
-Xmn8m \
-XX:InitialCodeCacheSize=4m \
-XX:ReservedCodeCacheSize=8m \
-XX:MaxDirectMemorySize=16m
如果使用REST API 的微服務(帶有 Feign 或 Ribbon),我們需要增加一些值:
-Xms16m \
-Xmx48m \
-XX:MaxMetaspaceSize=64m \
-XX:CompressedClassSpaceSize=8m \
-Xss256k \
-Xmn8m \
-XX:InitialCodeCacheSize=4m \
-XX:ReservedCodeCacheSize=8m \
-XX:MaxDirectMemorySize=16m
按照如上配置,JProfiler 生成瞭如下圖表。區別在於啟動和請求處理時間。與早期的設置相比,該應用程式的運行速度較慢。當然,我不會在生產環境下設置這樣的參數。
當前的總記憶體使用情況如下。微服務仍然是記憶體占用最大的,而Eureka 最小。
我也嘗試使用不同的 Web 容器運行 Eureka 應用程式。您可以通過在pom.xml
文件中包含以下的依賴關係輕鬆更改 Web 容器。
使用 Undertow
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
使用 Jetty
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
結果排名:Undertow(116MB)、Tomcat(122MB)、Jetty(128MB)。
此測試僅針對 Eureka 服務執行,而無需註冊任何微服務。
文末福利
Java 資料大全 鏈接:https://pan.baidu.com/s/1pUCCPstPnlGDCljtBVUsXQ 密碼:b2xc
更多資料: 2020 年 精選阿裡 Java、架構、微服務精選資料等,加 v ❤ :qwerdd111
轉載,請保留原文地址,謝謝 ~