
# 使用通用文件系统（原SFS 3.0 容量型）自动收集异常退出的JVM转储文件
当您使用Java开发业务时，如果设置的JVM堆空间过小，程序可能会出现OOM（Out Of Memory）问题。为了解决这个问题，您可以使用通用文件系统（原SFS 3.0 容量型）作为记录日志的载体，并将其挂载到容器内的相应目录中。当JVM发生OOM时，通用文件系统（原SFS 3.0 容量型）可以将日志记录到相应的目录中。
#### 前提条件
- 已创建CCE Standard集群，详情请参见[购买Standard/Turbo集群](https://support.huaweicloud.com/usermanual-cce/cce_10_0028.html)。
- 使用通用文件系统（原SFS 3.0 容量型）作为CCE 容器业务存储时，需要先配置VPC终端节点，通过VPC终端节点与通用文件系统（原SFS 3.0 容量型）建立通信。详情请参见[配置VPC终端节点](https://support.huaweicloud.com/usermanual-sfs/sfs_01_0134.html)。
 
#### 操作步骤
1. 基于通用文件系统（原SFS 3.0 容量型）创建一个PVC。 
   ```
   cat << EOF | kubectl apply -f -
   apiVersion: v1
   kind: PersistentVolumeClaim
   metadata:
     name: jvm-sfs-pvc
     namespace: default
     annotations: {}
   spec:
     accessModes:
       - ReadWriteMany
     resources:
       requests:
         storage: 10Gi
     storageClassName: csi-sfs
   EOF
   ```
   
   
2. 创建一个Deployment，用于模拟Java服务发生OOM，将产生的dump文件转储到绑定通用文件系统（原SFS 3.0 容量型）的PV中。 
   ```
   cat << EOF | kubectl apply -f -
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: java-application
     namespace: default
   spec:
     selector:
       matchLabels:
         app: java-application
     template:
       metadata:
         labels:
           app: java-application
       spec:
         containers:
         - name: java-application
           image: swr.cn-east-3.myhuaweicloud.com/container/java-oom-demo:v1  #本文中的镜像仅做示例
           imagePullPolicy: Always
           env: 
           - name: POD_NAME     #取metadata.name作为环境变量POD_NAME的值
             valueFrom:
               fieldRef:
                 apiVersion: v1
                 fieldPath: metadata.name
           - name: POD_NAMESPACE     #取metadata.namespace作为环境变量POD_NAMESPACE的值
             valueFrom:
               fieldRef:
                 apiVersion: v1
                 fieldPath: metadata.namespace
           args:
           - java                            #执行java命令
           - -Xms80m                         #设置堆内存的最小Heap值
           - -Xmx80m                         #设置堆内存的最大Heap值
           - -XX:HeapDumpPath=/mnt/oom/logs  #发生OOM时，堆内存转储的路径
           - -XX:+HeapDumpOnOutOfMemoryError #捕获堆发生OOM的错误
           - Mycode                          #执行示例镜像中的应用程序
           volumeMounts:
           - name: java-oom-pv
             mountPath: "/mnt/oom/logs"      #示例镜像容器内部使用/mnt/oom/logs作为日志的挂载目录
             subPathExpr: default.java-application   #使用$(POD_NAMESPACE).$(POD_NAME)的格式创建子目录，并将OOM转储文件生成到子目录中
         imagePullSecrets:
           - name: default-secret
         volumes:
         - name: java-oom-pv
           persistentVolumeClaim:
             claimName: jvm-sfs-pvc         #使用SFS的PVC，名称为jvm-sfs-pvc
   EOF
   ```
   ![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/note_3.0-zh-cn.png)
   以上示例中，为了体现挂载文件存储卷收集日志的模拟过程，参数配置均根据示例中的镜像进行了适配，实际使用中您需要根据实际的业务镜像进行调整。
   
   
3. 等待一会后，容器会发生OOM自动重启。 
   ```
   kubectl -n default get pod
   ```
   回显如下：
   ```
   NAME                                READY   STATUS    RESTARTS      AGE
   java-application-84dc6f897f-hc9q7   1/1     Running   1 (31s ago)   97s
   ```
   
   
4. 获取Java程序因为OOM产生的文件。 
   1. 前往[CCE控制台](https://console.huaweicloud.com/cce2.0/?#/cce/cluster/list)，单击集群名称进入集群，在左侧导航栏中选择"存储"，找到jvm-sfs-pvc的存储卷声明，单击关联的存储卷PV名称。
   
   2. 自动跳转到PVC对应的存储卷，单击关联的卷名称。
   
   3. 自动跳转到弹性文件服务控制台，复制挂载命令。 ![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000001826748154.png "点击放大")
      
   
   4. 登录一台集群节点，新建挂载点并运行挂载命令，挂载此通用文件系统存储卷。
      ```
      mkdir /test-jvm
      mount -t nfs -o vers=3,timeo=600,noresvport,nolock,proto=tcp ***.com:/pvc-4ea9137e-4101-4610-a4d2-9f8bb37043a1 /test-jvm
      ```
      
   
   5. 查看挂载的文件系统里的文件，目录中存在转储文件java_pid1.hprof。如果您需要定位到程序发生OOM的代码行数，可以将java_pid1.hprof下载到本地，通过MAT（Eclipse Memory Analyzer Tools）进一步分析JVM堆栈信息。
   
   
   
   
 
