SpringBoot的动态刷新配置
参考文献:spring boot 配置动态刷新
- 很多朋友只知道spring cloud config可以刷新远程git的配置到内存中,
- 却不知道spring cloud config的客户端可以脱离服务端使用,
- 更不知道spring cloud config客户端结合actuator还可以刷新本地的配置文件到内存中。
SpringBoot官网:
Spring Boot Actuator: Production-ready Features
https://docs.spring.io/spring-boot/docs/2.3.7.RELEASE/reference/html/production-ready-features.html#production-ready
效果展示
- 刷新前
- 修改
- postman刷新:
- 刷新后:
步骤
创建springboot项目
说明一下:项目的配置端口是80,我的演示是先跑起来服务,端口80,然后动态刷新到9090,之后改到1818的;然后再截图显示在这里的。
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xiaoyu</groupId>
<artifactId>autorefresh</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>autorefresh</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--监控+refresh配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
server.port=80
local.test=hello1
#management.security.enabled=false
management.endpoints.web.exposure.include=*
## management.endpoint.env.enabled=true
##
## # 启用端点 env
## management.endpoint.env.enabled=true
##
## # 暴露端点 env 配置多个,隔开
## management.endpoints.web.exposure.include=env
##
AutorefreshApplication
package com.xiaoyu.autorefresh;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AutorefreshApplication {
public static void main(String[] args) {
SpringApplication.run(AutorefreshApplication.class, args);
}
}
TestController
package com.xiaoyu.autorefresh.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class TestController {
private static int port;
@Value("${server.port}")
public void setPort(int p){
port = p;
}
@GetMapping("/port")
public int port(){
return port;
}
}
引申
- 上文中跑起来服务后,我们修改的是target目录下的配置文件。我们后知道java的代码是用
mvn package
打成为jar包后运行起来的,这个时候如何修改配置文件呢?
jar的配置可以在jar包所在的目录中,读取config目录下的配置文件。【参考springboot配置文件读取的顺序】,这样就可以将配置文件放在jar包所在的目录的config目录下,然后运行jar包就可以了。 - 在k8s中,通过configmap将配置文件挂在到config目录中。kubectl修改cm后,然后等待几秒钟,让配置动态刷新到pod中,然后调用动态刷新配置的端口。这样就可以实现配置文件的动态刷新了。
实现
package com.xiaoyu.autorefresh.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class TestController {
private static int port;
@Value("${local.test}")
private String test;
@Value("${server.port}")
public void setPort(int p){
port = p;
}
@GetMapping("/test")
public String test(){
return test;
}
@GetMapping("/port")
public int hello(){
return port;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xiaoyu</groupId>
<artifactId>autorefresh</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>autorefresh</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!--监控+refresh配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
server:
port: 8080
local:
test: qaz
management:
endpoints:
web:
exposure:
include: "*"
apiVersion: v1
data:
application.yml: |2-
server:
port: 8080
local:
test: 123123123123123123123xxxxxxxxxxxxxxxxxxxxxxxx000000000000
management:
endpoints:
web:
exposure:
include: "*"
kind: ConfigMap
metadata:
creationTimestamp: "2021-01-15T09:09:11Z"
name: auto-config
namespace: default
resourceVersion: "17915355"
selfLink: /api/v1/namespaces/default/configmaps/auto-config
uid: 551467c2-5711-11eb-9cae-0cda411dc04b
apiVersion: v1
kind: Service
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"name":"xiaoyuforauto"},"name":"xiaoyuforauto","namespace":"default"},"spec":{"ports":[{"name":"xiaoyuforauto","nodePort":19000,"port":8080,"protocol":"TCP","targetPort":8080}],"selector":{"name":"xiaoyuforauto"},"type":"NodePort"}}
creationTimestamp: "2021-01-15T03:34:49Z"
labels:
name: xiaoyuforauto
name: xiaoyuforauto
namespace: default
resourceVersion: "17879524"
selfLink: /api/v1/namespaces/default/services/xiaoyuforauto
uid: 9f137a33-56e2-11eb-8214-0cda411dc04b
spec:
clusterIP: 169.169.15.199
externalTrafficPolicy: Cluster
ports:
- name: xiaoyuforauto
nodePort: 19000
port: 8080
protocol: TCP
targetPort: 8080
selector:
name: xiaoyuforauto
sessionAffinity: None
type: NodePort
status:
loadBalancer: {
}
apiVersion: v1
kind: ReplicationController
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ReplicationController","metadata":{"annotations":{},"labels":{"name":"xiaoyuforauto"},"name":"xiaoyuforauto","namespace":"default"},"spec":{"selector":{"name":"xiaoyuforauto"},"template":{"metadata":{"labels":{"name":"xiaoyuforauto"}},"spec":{"containers":[{"image":"testredirect:0.0.1","name":"xiaoyuforauto","ports":[{"containerPort":8080,"protocol":"TCP"}]}],"nodeSelector":{"kubernetes.io/hostname":"192.168.11.151"}}}}}
creationTimestamp: "2021-01-15T03:04:20Z"
generation: 22
labels:
name: xiaoyuforauto
name: xiaoyuforauto
namespace: default
resourceVersion: "17914760"
selfLink: /api/v1/namespaces/default/replicationcontrollers/xiaoyuforauto
uid: 5ca10320-56de-11eb-8214-0cda411dc04b
spec:
replicas: 1
selector:
name: xiaoyuforauto
template:
metadata:
creationTimestamp: null
labels:
name: xiaoyuforauto
spec:
containers:
- args:
- java
- $(JAVA_OPT)
- -jar
- app.jar
env:
- name: JAVA_OPT
value: -XX:+UseParNewGC
image: testredirect:0.0.3
imagePullPolicy: IfNotPresent
name: xiaoyuforauto
ports:
- containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 500m
memory: 528Mi
requests:
cpu: 200m
memory: 528Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt/app/config
name: conf
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/hostname: 192.168.11.151
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {
}
terminationGracePeriodSeconds: 30
volumes:
- configMap:
defaultMode: 420
items:
- key: application.yml
path: application.yml
name: auto-config
name: conf
status:
availableReplicas: 1
fullyLabeledReplicas: 1
observedGeneration: 22
readyReplicas: 1
replicas: 1
- 修改cm
- 调用http://192.168.11.150:19000/actuator/refresh POST 一直等待返回值不是空
- http://192.168.11.150:19003/test GET返回最新
容器的CPU内存限制
# docker 容器对pod设置的资源限制是感知不到的,也就是在docker容器中
cat /proc/cpuinfo
cat /proc/meminfo
不会感应到pod设置的值,而是会直接使用宿主机的CPU内存
这样对于pod来说,如果我们只是设置了pod的资源限制,不对jvm做内存做设置,仅仅是java -jar **.jar。
此时会怎么样呢?
1:因为容器感应到的还是宿主机的CPU和memory,所以对于jvm来说,它设置初始值参考是宿主机的CPU和memory
2:因为pod自己设置了资源限制。所以k8s会在jvm使用超过了pod设置的资源限制时,把pod杀掉。
[root@localhost ~]# pod -w
NAME READY STATUS RESTARTS AGE
xiaoxufortest-sdftm 0/1 OOMKilled 0 35s
xiaoxufortest-sdftm 1/1 Running 1 35s
xiaoxufortest-sdftm 0/1 CrashLoopBackOff 1 77s
xiaoxufortest-sdftm 1/1 Running 2 78s
xiaoxufortest-sdftm 0/1 OOMKilled 2 105s
xiaoxufortest-sdftm 0/1 CrashLoopBackOff 2 117s
xiaoxufortest-sdftm 1/1 Running 3 2m12s
xiaoxufortest-sdftm 0/1 OOMKilled 3 2m37s
xiaoxufortest-sdftm 0/1 CrashLoopBackOff 3 2m49s
因此我们该怎么办??
1:不设置pod的资源限制,不太好
2:设置pod的资源限制,也对jvm的参数做限制
3:使用高版本的jdk【https://www.cnblogs.com/caoweixiong/p/12427202.html】
java 8u191+: UseContainerSupport默认开启
如下:
root@xiaoxufortest-wgfbl:/# cat /proc/meminfo
MemTotal: 12231696 kB
MemFree: 9045184 kB
MemAvailable: 10897604 kB
Buffers: 2104 kB
Cached: 1860692 kB
SwapCached: 0 kB
Active: 1374280 kB
Inactive: 1336704 kB
Active(anon): 848832 kB
Inactive(anon): 8712 kB
Active(file): 525448 kB
Inactive(file): 1327992 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 24 kB
Writeback: 0 kB
AnonPages: 848188 kB
Mapped: 279152 kB
Shmem: 9356 kB
Slab: 205552 kB
SReclaimable: 107140 kB
SUnreclaim: 98412 kB
KernelStack: 8704 kB
PageTables: 10844 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 6115848 kB
Committed_AS: 4179784 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 31272 kB
VmallocChunk: 34359611972 kB
HardwareCorrupted: 0 kB
AnonHugePages: 536576 kB
CmaTotal: 0 kB
CmaFree: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 122748 kB
DirectMap2M: 12460032 kB
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
stepping : 3
microcode : 0x1
cpu MHz : 2593.498
cache size : 4096 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm constant_tsc nopl eagerfpu pni cx16 x2apic popcnt hypervisor lahf_lm
bogomips : 5186.99
clflush size : 64
cache_alignment : 128
address sizes : 42 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
stepping : 3
microcode : 0x1
cpu MHz : 2593.498
cache size : 4096 KB
physical id : 1
siblings : 1
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm constant_tsc nopl eagerfpu pni cx16 x2apic popcnt hypervisor lahf_lm
bogomips : 5186.99
clflush size : 64
cache_alignment : 128
address sizes : 42 bits physical, 48 bits virtual
power management:
processor : 2
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
stepping : 3
microcode : 0x1
cpu MHz : 2593.498
cache size : 4096 KB
physical id : 2
siblings : 1
core id : 0
cpu cores : 1
apicid : 2
initial apicid : 2
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm constant_tsc nopl eagerfpu pni cx16 x2apic popcnt hypervisor lahf_lm
bogomips : 5186.99
clflush size : 64
cache_alignment : 128
address sizes : 42 bits physical, 48 bits virtual
power management:
processor : 3
vendor_id : GenuineIntel
cpu family : 15
model : 6
model name : Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
stepping : 3
microcode : 0x1
cpu MHz : 2593.498
cache size : 4096 KB
physical id : 3
siblings : 1
core id : 0
cpu cores : 1
apicid : 3
initial apicid : 3
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx lm constant_tsc nopl eagerfpu pni cx16 x2apic popcnt hypervisor lahf_lm
bogomips : 5186.99
clflush size : 64
cache_alignment : 128
address sizes : 42 bits physical, 48 bits virtual
power management:
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/# java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=6815736 -XX:MaxHeapSize=67108864 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
openjdk version "1.8.0_275"
OpenJDK Runtime Environment (build 1.8.0_275-b01)
OpenJDK 64-Bit Server VM (build 25.275-b01, mixed mode)
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/# java -XX:+PrintFlagsFinal -version > tt
openjdk version "1.8.0_275"
OpenJDK Runtime Environment (build 1.8.0_275-b01)
OpenJDK 64-Bit Server VM (build 25.275-b01, mixed mode)
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/# cat tt | grep UseContainerSupport
bool UseContainerSupport = true {
product}
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/# java Test # 这个是CPU的个数
1
root@xiaoxufortest-wgfbl:/#
root@xiaoxufortest-wgfbl:/#