SpringBoot的动态刷新配置

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

效果展示

  1. 刷新前
    在这里插入图片描述
  2. 修改
    在这里插入图片描述
  3. postman刷新:
    在这里插入图片描述
  4. 刷新后:
    在这里插入图片描述

步骤

创建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

  1. 修改cm
  2. 调用http://192.168.11.150:19000/actuator/refresh POST 一直等待返回值不是空
  3. 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:/#
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot的配置文件是基于Spring Framework的Environment和PropertySource抽象构建的。Spring Boot在启动时会创建一个Environment实例,该实例包含了应用程序中所有的属性和配置信息。在应用程序启动时,Spring Boot会将所有的配置文件加载到Environment中,然后将其包装到一个CompositePropertySource中。 当修改了配置文件时,Spring Boot会自动检测到文件的变化,并重新加载Environment中的属性和配置信息。这是通过使用Spring Boot的自动配置机制来实现的。自动配置机制会在应用程序启动时创建一个PropertySourceLoader,并使用它来加载配置文件。当文件发生变化时,自动配置机制会自动重新加载文件,并更新Environment中的属性和配置信息。 在Spring Boot中,可以使用@RefreshScope注解来实现动态刷新配置文件。该注解会使Spring Boot在属性值发生变化时自动更新Bean的值。具体来说,当使用@RefreshScope注解标注一个Bean时,Spring Boot会将该Bean包装在一个代理对象中,代理对象会在每次访问Bean时检查Bean的属性值是否发生了变化,如果发生了变化,则会重新创建Bean实例并返回新的实例。 总之,Spring Boot动态刷新配置文件的原理是通过自动检测配置文件的变化,重新加载属性和配置信息,并使用@RefreshScope注解将Bean包装在代理对象中,在属性值发生变化时重新创建Bean实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值