一篇"通过实例快速掌握 k8s(Kubernetes)核心概念[1]"讲解了 k8s 的核心概念,有了核心概念整个骨架就完整了,应付无状态程序已经够了,但还不够丰满。应用程序分成两种,无状态和有状态的。一般的前段和后端程序都是无状态的,而数据库是有状态的,他需要把数据存储起来,这样即使断电,数据也不会丢失。要创建有状态的程序,还需要引入另外一些 k8s 概念。它们虽然不是核心,但也很重要,共有三个,持久卷,网络和参数配置。掌握了这些之后,基本概念就已经做到了全覆盖,k8s 就已经入门了。我们通过搭建 MySQL 来熟悉这些 k8s 概念。容器本身是无状态的,一旦出现问题它会被随时销毁,它存储的数据也就丢失了。MySQL 需要一个能保存数据的持久层,在容器被销毁之后仍然存在,k8s 叫它持久卷。
在 k8s 上安装 MySQL 之前,先用 Docker 验证一下 MySQL 镜像:
docker run --name test-mysql -p 3306:33060 -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
“root”是根(root)用户的 password,这里是在创建 MySQL 容器时指定“root”用户的 password。“test-MySQL”是容器的名字。“mysql:5.7”用的是 docker 库里的“MySQL”5.7 版本。这次没有用最新的 8.0 版,因为新版跟以前的客户端不兼容,需要修改很多东西。所用的镜像是全版的 Linux,因而文件比较大,有 400M。
容器建好了之后,键入“docker logs test-mysql”,查看日志。
... 2019-10-03T06:18:50.439784Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.17' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL. 2019-10-03T06:18:50.446543Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060
查看容器状态。
vagrant@ubuntu-xenial:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3b9c50420f5b mysql:latest "docker-entrypoint.s…" 11 minutes ago Up 11 minutes 3306/tcp, 33060/tcp test-mysql
为了验证 MySQL,需要在虚机上安装 MySQL 客户端。
sudo apt-get -y -f install mysql-client
完成之后,键入“docker inspect test-mysql”找到容器 IP 地址, 下面显示"172.17.0.2"是容器 IP 地址。
vagrant@ubuntu-xenial:~$ docker inspect test-mysql ... "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", ...
键入“mysql -h 172.17.0.2 -P 3306 --protocol=tcp -u root -p”登录到 MySQL,"172.17.0.2"是 MySQL 的 IP 地址,“3306”是 MySQL 端口,是在创建镜像时设定的对外开放的端口,“root”是用户名,“-p”是 password 的参数选项。敲入命令后,系统要求输入 password,输入后,显示已成功连接到 MySQL。
vagrant@ubuntu-xenial:~$ mysql -h 172.17.0.2 -P 3306 --protocol=tcp -u root -p ... Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.7.27 MySQL Community Server (GPL) ...
在 k8s 上安装 MySQL 分成三个部分,创建部署文件,创建服务文件和安装测试。
部署(Deployment)文件
下面是部署配置文件。在上一篇文章中已经详细讲解了文件格式,所有的 k8s 的配置文件格式都是相同的。“template”之上是部署配置,从“template”向下是 Pod 配置。从“containers”开始是 Pod 里面的容器配置。“env:”是环境变量,这里通过环境变量来设置数据库的用户名和口令,后面还会详细讲解。MySQL 的端口是“3306”
apiVersion: apps/v1 kind: Deployment # 类型是部署 metadata: name: mysql-deployment # 对象的名字 spec: selector: matchLabels: app: mysql #用来绑定label是“mysql”的Pod strategy: type: Recreate template: # 开始定义Pod metadata: labels: app: mysql #Pod的Label,用来标识Pod spec: containers: # 开始定义Pod里面的容器 - image: mysql:5.7 name: mysql-con imagePullPolicy: Never env: # 定义环境变量 - name: MYSQL_ROOT_PASSWORD # 环境变量名 value: root # 环境变量值 - name: MYSQL_USER value: dbuser - name: MYSQL_PASSWORD value: dbuser args: ["--default-authentication-plugin=mysql_native_password"] ports: - containerPort: 3306 # mysql端口 name: mysql
下面是服务配置文件,这个与上一篇讲的配置基本相同,这里就不解释了。
apiVersion: v1 kind: Service metadata: name: mysql-service labels: app: mysql spec: type: NodePort selector: app: mysql ports: - protocol : TCP nodePort: 30306 port: 3306 targetPort: 3306
有了配置文件后,下面就开始创建 MySQL。在创建时要按照顺序,依次进行,先从最底层的对象开始创建。
kubectl apply -f mysql-deployment kubectl apply -f mysql-service.yaml
查看服务:
vagrant@ubuntu-xenial:~$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3h42m mysql-service NodePort 10.102.253.32 <none> 3306:30306/TCP 3h21m
“mysql-service”的端口(PORT(S))有两个,“3306”是 k8s 内部端口,“30306”是外部端口。由于“NodePort”已经打开了对外端口,这时就可以在虚拟机上通过“30306”端口访问 MySQL。
vagrant@ubuntu-xenial:~$ mysql -h localhost -P 30306 --protocol=tcp -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 6 Server version: 5.7.27 MySQL Community Server (GPL) ... mysql>
这时本地虚机已经与 k8s 联通了,下一步就可以在宿主机( 笔记本)上用图形客户端来访问 MySQL 了。我是在 Vagrant 里设定了私有网络,设定的虚机 IP 地址是 "192.168.50.4”,就用这个地址和 30306 端口来访问 MySQL。
这里的网络有两层含义,一层是 k8s 网络,就是让 k8s 内部服务之间可以互相访问,并且从 k8s 集群外部可以访问它内部的服务。另一层是宿主机(笔记本)和虚机之间的网路,就是在宿主机上可以访问虚机。这两层都通了之后,就可以在宿主机直接访问 k8s 集群里面的 MySQL。
k8s 的网络也有两层含义,一个是集群内部的,k8s 有内部 DNS,可以通过服务名进行寻址。另一个是从集群外部访问集群内部服务,一共有四种方式,详情请见“Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?[2]”
$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d nginx-service LoadBalancer 10.104.228.212 <pending> 80:31999/TCP 45h
下面是在运行“minikube tunnel ”(在另一个窗口运行)之后的服务信息,“EXTERNAL-IP”是 “10.104.228.212”。这时 Minikube 的 LoadBalancer 已经起作用了,现在就可以通过 IP 地址从外部访问 k8s 内部的服务了,“80”是 k8s 内部端口,“31999”是 k8s 对外端口。
$ kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31d nginx-service LoadBalancer 10.104.228.212 10.104.228.212 80:31999/TCP 45h
这是一种比较好的方式,但不能控制它的 IP 地址和端口,因此我暂时没有采用它。
这里讲的是宿主机(笔记本)和虚机之间的互相访问,主要是从宿主机访问虚机。我用的是 Vagrant, 因此要在 Vagran 的配置文件(Vagrantfile)里进行配置。它有两种方法:
当配置私有网络时,需要在笔记本的 VirtualBox 上配置“Host-only Adapter”,如下图所示。
但这会造成在 Vagrant 启动 Minikube 时产生如下错误:“VBoxManage.exe: error: Failed to create the host-only adapter”。这是 VirtualBox 的一个 Bug,你可以下载一个软件解决,详见这里[4]. 这个软件已经是四年之前的了,开始还担心是否与现在的 VirtualBox 版本兼容,结果很好用,而且它是一个单独运行的软件,不会与现在的软件冲突。只要在启动虚机之前,用管理员身份运行这个补丁就行了。另外一个问题是,我原来使用的是 5.x 版的 VirtualBox,上图中只能选“NAT”,不能选“Host-only Adapter”,升级到 6.X 之后才能选“Host-only Adapter”。但当虚机重新启动之后,它会自动变回“NAT”,不过私有网络还是可用。
k8s 卷的概念包括卷和持久卷。
卷是 k8s 的存储概念,它依附于 Pod,不能单独存在。但它不是在容器层。因此如果容器被重新启动,卷仍然在。但如果 Pod 重新启动,卷就丢失了。如果一个 Pod 里有多个容器,那么这些容器共享 Pod 的卷。你可以把卷看成是一个目录,里面可以存储各种文件。k8s 支持各种类型的卷,例如本地文件系统和各种云存储。
是对卷的一个封装,目的是为了更好地管理卷。它的生命周期不需要与 Pod 绑定,它可以独立于 Pod 存在。
是对持久卷资源的一个申请,你可以申请特定的存储容量的大小和访问模式,例如读写模式或只读模式。k8s 会根据持久卷申请分配适合的持久卷,如果没有合适的,系统会自动创建一个。持久卷申请是对持久卷的一个抽象,就像编程里的接口(Interface),它可以有不同的具体实现(持久卷)。例如,阿里云和华为云支持的存储系统不同,它生成的持久卷也不相同。持久卷是与特定的存储实现绑定的。那你要把程序从阿里云移植到华为云,怎么保证配置文件的兼容性呢?你就用持久卷申请来做这个接口,它只规定存储容量大小和访问模式,而由阿里云和华为云自动生成各自云里满足这个接口需求的持久卷. 不过,它还有一个限制条件,那就是持久卷申请和持久卷的 StorageClass 需要匹配,这使它没有接口灵活。后面会详细讲解。
在这种情况下,你只需创建持久卷申请(不需要单独创建持久卷),然后把持久卷申请与部署绑定。系统会按照持久卷申请自动创建持久卷。下面是持久卷申请配置文件。其中“storage:1Gi”,是指申请的空间大小是 1G。
持久卷申请配置文件:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim labels: app: mysql spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi #持久卷的容量是 1 GB
挂载持久卷申请的部署:
下面是挂载了持久卷申请的部署配置文件。它通过把持久卷申请当做持久卷来使用,与 Pod 进行绑定。请阅读文件里有关持久卷的注释。
apiVersion: apps/v1 kind: Deployment metadata: name: mysql-deployment spec: selector: matchLabels: app: mysql strategy: type: Recreate template: metadata: labels: app: mysql spec: containers: - image: mysql:5.7 name: mysql-con imagePullPolicy: Never env: - name: MYSQL_ROOT_PASSWORD value: root - name: MYSQL_USER value: dbuser - name: MYSQL_PASSWORD value: dbuser args: ["--default-authentication-plugin=mysql_native_password"] ports: - containerPort: 3306 name: mysql volumeMounts: # 挂载Pod上的卷到容器 - name: mysql-persistent-storage # Pod上卷的名字,与“volumes”名字匹配 mountPath: /var/lib/mysql # 挂载的Pod的目录 volumes: # 挂载持久卷到Pod - name: mysql-persistent-storage # 持久卷名字, 与“volumMounts”名字匹配 persistentVolumeClaim: claimName: mysql-pv-claim # 持久卷申请名字
这里只指定了 Pod 的挂载目录,并没有指定虚拟机(宿主机)的目录,后面会讲到如何找到虚拟机的目录(系统自动分配挂载目录)。
运行部署:
键入“kubectl apply -f mysql-volume.yaml”创建持久卷申请,在创建它的同时,系统自动创建持久卷。
查看持久卷申请
vagrant@ubuntu-xenial:~/dockerimages/kubernetes/mysql$ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mysql-pv-claim Bound pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa 1Gi RWO standard 10m
查看持久卷申请详细信息
vagrant@ubuntu-xenial:/mnt$ kubectl describe pvc mysql-pv-claim Name: mysql-pv-claim Namespace: default StorageClass: standard Status: Bound Volume: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa Labels: app=mysql ...
显示持久卷:
vagrant@ubuntu-xenial:/mnt$ kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa 1Gi RWO Delete Bound default/mysql-pv-claim standard 24h
键入“kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa”, 显示持久卷详细信息。从这里可以看出,虚拟机上的持久卷在如下位置:“Path:/tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa”。
vagrant@ubuntu-xenial:/mnt$ kubectl describe pv pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa Name: pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa Labels: <none> Annotations: hostPathProvisionerIdentity: 19948fdf-e67f-11e9-8fbd-026a5b40726f pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath Finalizers: [kubernetes.io/pv-protection] StorageClass: standard Status: Bound Claim: default/mysql-pv-claim Reclaim Policy: Delete Access Modes: RWO VolumeMode: Filesystem Capacity: 1Gi Node Affinity: <none> Message: Source: Type: HostPath (bare host directory volume) Path: /tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa HostPathType: Events: <none>
查看 MySQL 目录信息:
vagrant@ubuntu-xenial:/tmp/hostpath-provisioner/pvc-ac6c88d5-ef5a-4a5c-b499-59715a2d60fa$ ls -al total 188488 drwxrwxrwx 6 999 docker 4096 Oct 4 13:23 . drwxr-xr-x 3 root root 4096 Oct 4 12:58 .. -rw-r----- 1 999 docker 56 Oct 4 12:58 auto.cnf -rw------- 1 999 docker 1679 Oct 4 12:59 ca-key.pem -rw-r--r-- 1 999 docker 1107 Oct 4 12:59 ca.pem -rw-r--r-- 1 999 docker 1107 Oct 4 12:59 client-cert.pem -rw------- 1 999 docker 1679 Oct 4 12:59 client-key.pem -rw-r----- 1 999 docker 668 Oct 4 13:21 ib_buffer_pool -rw-r----- 1 999 docker 79691776 Oct 4 13:23 ibdata1 -rw-r----- 1 999 docker 50331648 Oct 4 13:23 ib_logfile0 -rw-r----- 1 999 docker 50331648 Oct 4 12:58 ib_logfile1 -rw-r----- 1 999 docker 12582912 Oct 4 13:24 ibtmp1 drwxr-x--- 2 999 docker 4096 Oct 4 12:58 mysql drwxr-x--- 2 999 docker 4096 Oct 4 12:58 performance_schema -rw------- 1 999 docker 1679 Oct 4 12:59 private_key.pem -rw-r--r-- 1 999 docker 451 Oct 4 12:59 public_key.pem -rw-r--r-- 1 999 docker 1107 Oct 4 12:59 server-cert.pem -rw------- 1 999 docker 1675 Oct 4 12:59 server-key.pem drwxr-x--- 2 999 docker 4096 Oct 4 13:18 service_config drwxr-x--- 2 999 docker 12288 Oct 4 12:58 sys
持久卷的回收模式:
当持久卷和持久卷申请被删除后,它有三种回收模式。
动态持久卷的一个问题是它的缺省回收模式是“删除”,这样当虚机重新启动后,持久卷会被删除。当你重新运行部署时,k8s 会创建一个新的 MySQL,这样原来 MySQL 里的新建信息就会丢失,这是我们不愿意看到的。虽然你可以手动修改回收方式为“保持”,但还是要手动回收原来持久卷里的数据。一个解决办法是把持久卷建在宿主机上,这样即使虚机出了问题被重新启动,MySQL 里的新建信息依然不会丢失。如果是在云上,就会有专门的的存储层,如果是本地,大致有三种方式:
我选择了比较简单的“Local”方式。在这种方式下,必须单独创建持久卷,不能 只创建持久卷申请而让系统自动创建持久卷。
下面是使用“Local”方式的配置文件,它把持久卷和持久卷申请写在了一个文件里。当用“Local”方式时,需要设置“nodeAffinity”部分,其中“values:- minikube” 的“Minikube”是 k8s 集群 Node 的名字,“Minikube”只支持一个 Node,既是“Master Node”,又是“Worker Node”。
持久卷和申请的配置文件:
apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce storageClassName: standard #持久卷存储类型,它需要与持久卷申请的类型相匹配 local: path: /home/vagrant/database/mysql #宿主机的目录 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - minikube # Node的名字 --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim labels: app: mysql spec: accessModes: - ReadWriteOnce # storageClassName: # 这里的存储类型注释掉了 resources: requests: storage: 1Gi #1 GB
如果不知道 Node 名字,可用如下命令查看:
vagrant@ubuntu-xenial:/$ kubectl get node NAME STATUS ROLES AGE VERSION minikube Ready master 6d3h v1.15.2
改用静态持久卷之后,只有持久卷配置文件发生了变化,部署和服务的配置文件没有变。重新运行持久卷和部署,成功之后,即使重启虚拟机,MySQL 里面的新建内容也没有丢失。
注意这里 storageClassName 的用法。k8s 规定持久卷和持久卷申请的 storageClassName 必须匹配,这时才会把持久卷分配给持久卷申请。我们这里的持久卷申请没有指定 storageClassName,这时系统会使用缺省的 storageClass。
查看是否安装了缺省的 storageClass
vagrant@ubuntu-xenial:/$ kubectl get sc NAME PROVISIONER AGE standard (default) k8s.io/minikube-hostpath 6d3h vagrant@ubuntu-xenial:/$
查看缺省的 storageClass 详细信息
vagrant@ubuntu-xenial:/$ kubectl describe sc Name: standard IsDefaultClass: Yes Annotations: storageclass.kubernetes.io/is-default-class=true Provisioner: k8s.io/minikube-hostpath Parameters: <none> AllowVolumeExpansion: <unset> MountOptions: <none> ReclaimPolicy: Delete VolumeBindingMode: Immediate Events: <none>
从这里可以看出,Minikube 安装了缺省的 storageClass,它的名字是“standard”。上面的持久卷申请里没有指定 storageClass,因此系统使用缺省的 storageClass 与之匹配,而上面的持久卷的 storageClassName 是“standard”,正好能配上。详情请见“Dynamic Provisioning and Storage Classes in Kubernetes[8]”
踩过的坑:
当用“minikube start --vm-driver=virtualbox”时,你是先建了虚拟机,再在虚拟机上运行 Minikube。当用“minikube start --vm-driver=none”时,是直接在宿主机上运行 Minikube。但由于我的 Windows 版本不能直接支持 k8s,我已经在 Windows 上装了 Linux 虚机,并用 Vagrant 进行管理。如果用“minikube start --vm-driver=virtualbox”,就是在 Linux 虚机上又装了一个虚机。现在用“minikube start --vm-driver=none”,表面上看是在宿主机上运行,实际上已经运行在 Windows 的 Linux 虚机上了。
" kubectl exec -ti mysql-deployment-56c9cf5857-fffth -- /bin/bash"。其中“mysql-deployment-56c9cf5857-fffth”是 Pod 名字。
The persistentvolumeclaim "mysql-pv-claim" is invalid: spec: forbidden: is immutable after creation except resources.requests for bound claims 这时,你需要将原来的 PV 或 PVC 删掉,再重新创建新的。
喜欢本文的朋友,欢迎关注“Go语言中文网”:
参考资料
[1]通过实例快速掌握k8s(Kubernetes)核心概念: https://blog.csdn.net/weixin_38748858/article/details/102132544
[2]Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?: https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0
[3]“Vagrant reverse port forwarding?”: https://stackoverflow.com/a/17012410
[4]详见这里: https://www.virtualbox.org/attachment/ticket/14040/VBox-Win10-fix-14040.exe
[5]Volumes: https://kubernetes.io/docs/concepts/storage/volumes/#local
[6]hostPath as volume in kubernetes: https://stackoverflow.com/questions/50001403/hostpath-as-volume-in-kubernetes
[7]Kubernetes Volumes Guide: https://matthewpalmer.net/kubernetes-app-developer/articles/kubernetes-volumes-example-nfs-persistent-volume.html
[8]Dynamic Provisioning and Storage Classes in Kubernetes: https://kubernetes.io/blog/2017/03/dynamic-provisioning-and-storage-classes-kubernetes/
本文作者: 倚天码农
原文链接:https://segmentfault.com/a/1190000020669205
者:SimpleSmile_5177
来源:https://www.cnblogs.com/Simple-Object/p/10272326.html
大家都知道,jvm在启动的时候,会执行默认的一些参数。一般情况下,这些设置的默认参数应对一些平常的项目也够用了。但是如果项目特别大了,需要增加一下堆内存的大小、或者是系统老是莫明的挂掉,想查看下gc日志来排查一下错误的原因,都需要咱们手动设置这些参数。
表示,启动jvm的时候,输出jvm里面的gc信息。格式如下:
[Full GC 178K->99K(1984K), 0.0253877 secs]
解读 :Full GC 就表示执行了一次Full GC的操作,178K 和99K 就表示执行GC前内存容量和执行GC后的内存容量。1984K就表示内存总容量。后面那个是执行本次GC所消耗的时间,单位是秒。
这个打印的GC信息跟上个一样,就不做介绍了。
打印GC的详细信息。格式如下:
解读:new generation 就是堆内存里面的新生代。total的意思就是一共的,所以后面跟的就是新生代一共的内存大小。used也就是使用了多少内存大小。0x开头的那三个分别代表的是 底边界,当前边界,高边界。也就是新生代这片内存的起始点,当前使用到的地方和最大的内存地点。
eden space 这个通常被翻译成伊甸园区,是在新生代里面的,一些创建的对象都会先被放进这里。后面那个12288K就表示伊甸园区一共的内存大小,91% used,很明显,表示已经使用了百分之多少。后面的那个0x跟上一行的解释一样。
from space 和to space 是幸存者的两个区。也是属于新生代的。他两个区的大小必须是一样的。因为新生代的GC采用的是复制算法,每次只会用到一个幸存区,当一个幸存区满了的时候,把还是活的对象复制到另个幸存区,上个直接清空。这样做就不会产生内存碎片了。
tenured generation 就表示老年代。
compacting perm 表示永久代。由于这两个的格式跟前面我介绍的那个几乎一样,我就不必介绍了。
打印GC发生的时间戳。格式如下:
289.556: [GC [PSYoungGen: 314113K->15937K(300928K)] 405513K->107901K(407680K), 0.0178568 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
293.271: [GC [PSYoungGen: 300865K->6577K(310720K)] 392829K->108873K(417472K), 0.0176464 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
解读:289.556表示从jvm启动到发生垃圾回收所经历的的时间。GC表示这是新生代GC(Minor GC)。PSYoungGen表示新生代使用的是多线程垃圾回收器Parallel Scavenge。314113K->15937K(300928K)]这个跟上面那个GC格式一样,只不过,这个是表示的是新生代,幸存者区。后面那个是整个堆的大小,GC前和GC后的情况。Times这个显而易见,代表GC的所消耗的时间,用户垃圾回收的时间和系统消耗的时间和最终真实的消耗时间。
这个就表示,指定输出gc.log的文件位置。(我这里写的log/gc.log就表示在当前log的目录里,把GC日志写到叫gc.log的文件里。)
表示每次GC后,都打印堆的信息。(这个打印的基本格式跟上面第二条的基本类似,我也就不比多说了。)
监控类的加载。格式如下:
使用这个参数就能很清楚的看到那些类被加载的情况了。
跟踪参数。这个按下Ctrl+Break后,就会打印一下信息:
–分别显示:序号、实例数量、总大小、类型。
这里面那个类型,B和C的其实就是byte和char类型。
这个就表示设置堆内存的最大值和最小值。这个设置了最大值和最小值后,jvm启动后,并不会直接让堆内存就扩大到指定的最大数值。而是会先开辟指定的最小堆内存,如果经过数次GC后,还不能,满足程序的运行,才会逐渐的扩容堆的大小,但也不是直接扩大到最大内存。
设置新生代的内存大小。
新生代和老年代的比例。比如:1:4,就是新生代占五分之一。
设置两个Survivor区和eden区的比例。比如:2:8 ,就是一个Survivor区占十分之一。
发生OOM时,导出堆的信息到文件。
表示,导出堆信息的文件路径。
当系统产生OOM时,执行一个指定的脚本,这个脚本可以是任意功能的。比如生成当前线程的dump文件,或者是发送邮件和重启系统。
设置永久区的内存大小和最大值。永久区内存用光也会导致OOM的发生。
设置栈的大小。栈都是每个线程独有一个,所有一般都是几百k的大小。
buntu信息如下。
root@hanyw:~#
root@hanyw:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.1 LTS
Release: 22.04
Codename: jammy
root@hanyw:~#
root@hanyw:~#
root@hanyw:~# uname -r
5.15.0-53-generic
GCC帮助手册的第19小节,第12288~13288行,如下。
*请认真填写需求信息,我们会在24小时内与您取得联系。