作者:小傅哥 博客:https://bugstack.cn
❝沉淀、分享、成长,让自己和他人都能有所收获!😜 ❞
大家好,我是技术UP主小傅哥。
在互联网公司中开发的项目经常有一种场景,是在不重启应用的情况下,变更应用中某个属性信息的值。比如,我们为系统新增加允许外部调用接入的SC渠道值,测试阶段验证名单PIN、持续发布上线后的切量。这些东西都是不重启应用的情况下,动态做配置变更,那这样的东西在 SpringCloud 有什么现成的组件可以使用呢?
在大厂这个组件叫什么?
这个东西它不同于 Redis,而是把配置写到本地类对应的属性上。而不是像 Redis 那样从一个统一的地方每次去取使用。在大厂中我们管这个组件叫统一配置中,专门应对分布式工程中类对应属性的值的控制。
在小傅哥的大营销项目中,也带着大家实现过这样一款组件,叫DCC,基于 Zookeeper + AOP 切面实现。
那么我们本节来看看 SpringCloud 是如何来处理这样一个场景的。
Spring Cloud Bus 将分布式系统的节点与轻量级消息代理相链接。然后可以使用它来广播状态更改(例如配置更改)或其他管理指令。该项目包含 AMQP 和 Kafka 代理实现。
在微服务架构中,通常使用轻量级的消息代理来创建一个共享的消息主题,让所有微服务实例都可以连接到这个主题上。因为这个主题中的消息会被所有实例监听和消费,因此通常称之为“消息总线”。连接到总线的每个实例都可以轻松地广播消息,以便所有其他连接该主题的实例能够接收到这些信息。
小傅哥这里搭建了一套用于测试验证 SpringCloud Bus 消息总线的服务。
**工程**:[https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus](https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus) - `你可以把工程fork到你的github仓库,之后做后面的操作。`
本节的案例工程会需要用到 Kafka、RabbitMQ,所以需要安装这两套环境。
@Configuration
@PropertySource("classpath:system.properties")
public class KafkaConfig {
}
spring.kafka.bootstrap-servers=127.0.0.1:9092
spring.kafka.producer.retries=0
spring.kafka.producer.batch-size=16384
spring.kafka.producer.buffer-memory=33554432
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.consumer.group-id=springcloud-config-bus-group
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-commit-interval=100
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
package cn.bugstack.xfg.dev.tech;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class ConfigBusRegistryApplication {
public static void main(String[] args) {
SpringApplication.run( ConfigBusRegistryApplication.class, args );
}
}
server:
port: 7397
spring:
application:
name: eureka-server
eureka:
instance:
# 使用 ip 代替实例名
prefer-ip-address: true
# 实例的主机名
hostname: ${spring.cloud.client.ip-address}
# 实例的 ID 规则
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
# 是否向注册中心注册自己
registerWithEureka: false
# 是否向注册中心获取注册信息
fetchRegistry: false
serviceUrl:
# 注册中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
package cn.bugstack.xfg.dev.tech;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigBusServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigBusServerApplication.class, args);
}
}
# 端口
server:
port: 8000
spring:
application:
name: config-bus-server
cloud:
config:
server:
git:
# 仓库地址
uri: https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus
# 对应 {label} 部分,即 Git 的分支
label: master
# 仓库文件夹名称,多个以逗号分隔
search-paths: config-bus/config-repo
# git 仓库用户名(公开库可以不用填写)
username:
# git 仓库密码(公开库可以不用填写)
password:
bus:
# 开启消息跟踪
enabled: true
trace:
enabled: true
kafka:
consumer:
group-id: config-bus-server-group
eureka:
instance:
prefer-ip-address: true
hostname: ${spring.cloud.client.ip-address}
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:7397/eureka/
management:
endpoints:
web:
exposure:
# 开启刷新端点
include: bus-refresh
system-dev.properties
hello=I'm xfg dev config 09
hi=I'm xfg dev config 08
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${hello}")
private String hi;
@RequestMapping("/hi")
public String hi() {
return this.hi;
}
}
验证时访问地址;http://127.0.0.1:9000/hi
package cn.bugstack.xfg.dev.tech.trigger;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
@Slf4j
@RestController
public class GitHubWebhookController {
@PostMapping("/webhook")
public String handleGitWebhook(@RequestBody String payload) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode content = mapper.readTree(payload);
log.info("收到 webhook {} 更新配置通知", content.get("pusher"));
// 创建URL对象
URL url = new URL("http://127.0.0.1:8000/actuator/bus-refresh");
// 打开连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法为POST
connection.setRequestMethod("POST");
// 开启输入输出流
connection.setDoOutput(true);
// 设置请求头,如果需要,可以设置Content-Type等
connection.setRequestProperty("Content-Type", "application/json");
// 获取输出流
try (OutputStream os = connection.getOutputStream()) {
// 如果有请求体数据,也可以在这里写入
// String jsonInputString = "{\"key\": \"value\"}";
// os.write(jsonInputString.getBytes("utf-8"));
os.flush();
}
// 发送请求并获取响应码
int responseCode = connection.getResponseCode();
log.info("调用 actuator/bus-refresh 更新全局配置完成 code:{}", responseCode);
} catch (Exception e) {
e.printStackTrace();
}
return "done";
}
}
http://127.0.0.1:8000/actuator/bus-refresh
刷新配置。http://127.0.0.1:8000/actuator/bus-refresh
自己刷新配置验证。获取 natapp 免费隧道 authtoken,https://natapp.cn/tunnel/lists 配置到工程中。
进入 GitHub 工程中,Settings -> Webhooks 页面。地址:https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus/settings/hooks/517530722 - 你的和我的不同
陆续的启动;config-bus-registry、config-bus-server、xfg-dev-tech-app。
地址:http://127.0.0.1:9000/hi
I'm xfg dev config 09
webhook {"name":"fuzhengwei","email":"fuzhengwei@users.noreply.github.com"} 更新配置通知
地址:http://127.0.0.1:9000/hi
I'm xfg dev config 10
{
"name": "system",
"profiles": [
"dev"
],
"label": null,
"version": "fccaf3233af6d0ae16571d2c907ff87eaf1c8946",
"state": null,
"propertySources": [
{
"name": "https://github.com/fuzhengwei/xfg-dev-tech-springcloud-bus/config-bus/config-repo/system-dev.properties",
"source": {
"hello": "I'm xfg dev config 10",
"hi": "I'm xfg dev config 08"
}
}
]
}
- END -
加入小傅哥的星球「码农会锁」,💐斩获大厂Offer!阅读500+份简历和评审,学习6个业务项目;MVC+DDD,双架构开发小型电商
、大营销(超级大课)
、OpenAI 大模型应用
、Lottery
、IM
、AI 问答助手
。7个组件项目;OpenAI 代码评审
、BCP 透视业务监控
、动态线程池
、支付SDK设计和开发
、API网关
、SpringBoot Starter
、IDEA Plugin 插件开发
。1套源码课程、1套基础教程、1到云服务器教程以及各类场景解决方案。
小傅哥有那么多课程内容,我加入后都可以学习吗?可以!
好啦,这就是小傅哥的技术列车🚌,嘎嘎实惠!🤔 几乎没有哪个大厂架构师,用这么一个普惠的价格手把手的教大家学习了。
星球「码农会锁」- 加入后从课程入口进入项目学习
星球全程手把手指导教学,遇到技术问题帮忙排查代码。已经有很多伙伴开始学起来了,还有大家交的作业笔记。有了的项目驱动学习,清晰的目标感,大家冲起来也有了更明确的方向!干干干!!!