如何從 Kubernetes Pod 獲取 Java Heap Dump?
一、概述
Java 以其出色的垃圾收集器算法而聞名。但是,這並不意味著 JVM 應用程序中不會發生內存洩漏。獲取和分析堆轉儲是在我們的應用程序中發現潛在洩漏的第一步。
在這個簡短的教程中,我們將了解如何從作為 Kubernetes pod 運行的應用程序中獲取 Java 堆轉儲。
首先,我們將研究堆轉儲是什麼。然後,我們將創建一個小型測試應用程序,稍後將作為 pod 部署到 Kubernetes。最後,我們將看到如何從中獲取堆轉儲。
2. 什麼是堆轉儲
堆轉儲是 JVM 應用程序內存中所有對像在特定時刻的快照。
通過查看堆並使用特殊工具對其進行分析,我們可以找到創建對象的位置,並在源中找到對這些對象的引用。我們還可以看到一張圖表,顯示整個時間的內存分配。
因此,堆轉儲有助於檢測內存洩漏問題並優化 JVM 應用程序中的內存使用。
3. 創建測試應用
在捕獲堆轉儲之前,我們需要在 Kubernetes pod 中運行一個 JVM 應用程序。
3.1.創建一個長時間運行的應用程序
讓我們創建一個簡單的應用程序來搜索指定範圍內的素數。我們將其稱為prime-number-finder.
我們的小應用程序包含一個main()
方法和一個isPrime()
方法來運行暴力素數檢測器:
public static void main(String[] args) {
List<Integer> primes = new ArrayList<>();
int maxNumber = Integer.MAX_VALUE; // set to huge to make it run a long time
for (int i = 2; i < maxNumber; i++) {
if (isPrime(i)) {
System.out.println(i);
primes.add(i);
}
}
}
private static boolean isPrime(int number) {
return IntStream.rangeClosed(2, (int) (Math.sqrt(number)))
.allMatch(n -> number % n != 0);
}
下一步是將我們的代碼編譯成一個jar
文件。它將被稱為prime-number-finder.jar
並將位於target
目錄中。
3.2.容器化 Kubernetes 應用程序
為了能夠將其部署到 Kubernetes 堆棧,讓我們創建一個 dockerfile:
FROM adoptopenjdk:11-jre-hotspot
COPY target/prime-number-finder.jar application.jar
ENTRYPOINT ["java", "-jar", "application.jar"]
我們將構建的jar
文件複製到一個容器中,並使用標準的java -jar
命令運行它。
接下來,我們需要一個prime-deploy.yaml
Kubernetes 部署文件,它指定如何將我們的應用程序部署到 Kubernetes 堆棧:
apiVersion: v1
kind: Pod
metadata:
name: prime-number-finder-pod
spec:
containers:
- name: prime-number-finder
image: baeldung/prime-number:latest
我們需要做的最後一件事是將其部署到 Kubernetes:
$ kubectl apply -f prime-deploy.yaml
如果部署成功,我們可以使用kubectl get pods
命令來檢查:
NAME READY STATUS RESTARTS AGE IP NODE
prime-number-finder-pod 1/1 Running 0 1m 172.17.0.3 minikube
4.獲取堆轉儲
我們需要做的第一件事是獲取正在運行的 pod 的名稱。我們可以從上一章的kubectl get pods
命令中獲取它。在我們的例子中,它是prime-number-finder-pod
。
下一步是使用該名稱進入我們正在運行的 pod 。我們將使用 Kubernetes exec
命令來執行此操作:
$ kubectl exec -it prime-number-finder-pod bash
現在,我們需要獲取正在運行的 JVM 應用程序的進程 ID 。我們可以使用 JDK 內置的jps
命令。
下一步是創建堆轉儲。我們將再次使用內置的 JDK 工具:
$ jmap -dump:live,format=b,file=prime_number_heap_dump.bin <process_id>
我們需要做的最後一件事是將新創建的堆轉儲從 pod 複製到我們的本地機器:
$ kubectl cp prime-number-finder-pod:prime_number_heap_dump.bin <our local destination directory>
現在,我們可以使用任何內存分析工具,例如 JDK 自帶的 JvisualVM,或者第三方應用程序,例如 JProfiler 或 JStack Review,來分析堆轉儲
這是一個 10 分鐘質數應用程序在 JvisualVM 中的堆轉儲分析的樣子:
5.結論
在本文中,我們學習瞭如何從 Kubernetes pod 獲取 Java 堆轉儲。
首先,我們了解什麼是堆轉儲及其用途。然後,我們創建了一個簡單的素數查找器應用程序並將其部署到 Kubernetes。
最後,我們展示瞭如何登錄到正在運行的 pod,創建堆轉儲並將其複製到本地機器。
一如既往,本文的完整源代碼可在 GitHub 上獲得。