<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Spring Cloud Bus on 小蜜蜂</title>
        <link>https://xumf.net/tags/spring-cloud-bus/</link>
        <description>Recent content in Spring Cloud Bus on 小蜜蜂</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Fri, 05 Jan 2024 13:42:22 +0800</lastBuildDate><atom:link href="https://xumf.net/tags/spring-cloud-bus/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Spring Cloud Bus</title>
            <link>https://xumf.net/blog/springcloudbus/</link>
            <pubDate>Fri, 05 Jan 2024 13:42:22 +0800</pubDate>
            <guid>https://xumf.net/blog/springcloudbus/</guid>
            <description>&lt;h2 id=&#34;spring-cloud-bus-的核心概念&#34;&gt;Spring Cloud Bus 的核心概念&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1什么是-spring-cloud-bus&#34;&gt;（1）什么是 Spring Cloud Bus？&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;Spring Cloud Bus 是一个分布式事件总线，用于在微服务之间传播状态变化（如配置更新）&lt;/li&gt;&#xA;&lt;li&gt;它基于消息中间件（RabbitMQ、Kafka）实现，解决 Config Server 逐台通知的痛点——没有 Bus 时，配置变更后需要逐一重启或手动调用每个客户端端点的 &lt;code&gt;refresh&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;与 Spring Cloud Config 配合使用是主流场景，但 Bus 本身不依赖 Config——任何需要广播的事件都可以通过 Bus 传播&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;2spring-cloud-bus-的组成&#34;&gt;（2）Spring Cloud Bus 的组成&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;消息中间件&lt;/strong&gt;：RabbitMQ 或 Kafka，负责传递事件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;事件生产者&lt;/strong&gt;：Config Server 或其他微服务，发送事件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;事件消费者&lt;/strong&gt;：Config Client 或其他微服务，接收事件并执行相应操作&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;3spring-cloud-bus-的特点&#34;&gt;（3）Spring Cloud Bus 的特点&#xA;&lt;/h3&gt;&lt;ul&gt;&#xA;&lt;li&gt;全局配置刷新：通过 &lt;code&gt;/actuator/bus-refresh&lt;/code&gt; 端点触发全局配置刷新&lt;/li&gt;&#xA;&lt;li&gt;服务状态同步：通过事件传播实现服务状态同步&lt;/li&gt;&#xA;&lt;li&gt;多消息中间件支持：支持 RabbitMQ 和 Kafka&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;定点通知&lt;/strong&gt;：支持指定某个或某几个服务实例刷新（&lt;code&gt;/actuator/bus-refresh/{destination}&lt;/code&gt;），避免全量广播&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;spring-cloud-bus-的工作原理&#34;&gt;Spring Cloud Bus 的工作原理&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1事件传播流程&#34;&gt;（1）事件传播流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;事件生产者（如 Config Server）发送事件到消息中间件&lt;/li&gt;&#xA;&lt;li&gt;消息中间件将事件广播给所有订阅该队列的消费者&lt;/li&gt;&#xA;&lt;li&gt;事件消费者接收到事件并执行相应操作&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;关键：每个 Bus 客户端启动时会在消息中间件中创建自己的唯一队列（基于 &lt;code&gt;spring.cloud.bus.id&lt;/code&gt;），Bus 通过这个队列实现定点通知——&lt;code&gt;/bus-refresh/user-service:**&lt;/code&gt; 只会发送给 service ID 为 user-service 的实例。&lt;/p&gt;&#xA;&lt;h3 id=&#34;2全局配置刷新流程&#34;&gt;（2）全局配置刷新流程&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;管理员调用 POST &lt;code&gt;/actuator/bus-refresh&lt;/code&gt;（向任意一个 Bus 客户端请求即可——它会通过消息中间件广播给所有实例）&lt;/li&gt;&#xA;&lt;li&gt;该客户端发布 &lt;code&gt;RefreshRemoteApplicationEvent&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;消息中间件广播该事件&lt;/li&gt;&#xA;&lt;li&gt;所有 Config Client 监听到事件，调用 &lt;code&gt;ContextRefresher.refresh()&lt;/code&gt; → &lt;code&gt;RefreshScope.refreshAll()&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;标记了 &lt;code&gt;@RefreshScope&lt;/code&gt; 的 Bean 被销毁并重新创建，加载新配置&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;spring-cloud-bus-的配置&#34;&gt;Spring Cloud Bus 的配置&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1rabbitmq-配置&#34;&gt;（1）RabbitMQ 配置&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spring&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;rabbitmq&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;host&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;localhost&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;5672&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;username&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;guest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;password&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;guest&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2kafka-配置&#34;&gt;（2）Kafka 配置&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spring&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;kafka&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;bootstrap-servers&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;localhost:9092&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;consumer&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;group-id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;my-group&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;3添加依赖&#34;&gt;（3）添加依赖&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.cloud&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-cloud-starter-bus-amqp&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- RabbitMQ --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- 或 --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- &amp;lt;artifactId&amp;gt;spring-cloud-starter-bus-kafka&amp;lt;/artifactId&amp;gt; --&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!-- Kafka --&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;4暴露-actuator-端点&#34;&gt;（4）暴露 Actuator 端点&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;management&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;endpoints&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;web&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;exposure&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;include&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;bus-refresh&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;spring-cloud-bus-的使用场景&#34;&gt;Spring Cloud Bus 的使用场景&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1全局配置刷新&#34;&gt;（1）全局配置刷新&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 全量刷新&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST http://localhost:8888/actuator/bus-refresh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 定点刷新（只刷新 user-service）&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -X POST http://localhost:8888/actuator/bus-refresh/user-service:**&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2自定义事件&#34;&gt;（2）自定义事件&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 发送自定义事件&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Autowired&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; ApplicationEventPublisher publisher;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sendCustomEvent&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    publisher.&lt;span style=&#34;color:#a6e22e&#34;&gt;publishEvent&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; MyCustomEvent(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;custom-data&amp;#34;&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 接收自定义事件&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@EventListener&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handleCustomEvent&lt;/span&gt;(MyCustomEvent event) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 处理事件&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：自定义事件必须继承 &lt;code&gt;RemoteApplicationEvent&lt;/code&gt; 才能通过 Bus 传播到其他服务节点，否则只会在本地发布。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3指定服务刷新的场景&#34;&gt;（3）指定服务刷新的场景&#xA;&lt;/h3&gt;&lt;p&gt;当集群中不同服务配置不同时，全量刷新可能造成混乱。定点刷新适用于：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;灰度配置发布：只刷新新版本的服务实例&lt;/li&gt;&#xA;&lt;li&gt;分批部署：一组一组刷新，观察无问题后再继续&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;spring-cloud-bus-源码概览&#34;&gt;Spring Cloud Bus 源码概览&#xA;&lt;/h2&gt;&lt;h3 id=&#34;1busrefreshendpoint&#34;&gt;（1）BusRefreshEndpoint&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Endpoint&lt;/span&gt;(id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;bus-refresh&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BusRefreshEndpoint&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ApplicationEventPublisher publisher;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BusRefreshEndpoint&lt;/span&gt;(ApplicationEventPublisher publisher) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;publisher&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; publisher;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@WriteOperation&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;refresh&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        publisher.&lt;span style=&#34;color:#a6e22e&#34;&gt;publishEvent&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; RefreshRemoteApplicationEvent(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;));&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2refreshremoteapplicationevent&#34;&gt;（2）RefreshRemoteApplicationEvent&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RefreshRemoteApplicationEvent&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; RemoteApplicationEvent {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RefreshRemoteApplicationEvent&lt;/span&gt;(Object source, String originService, String destinationService) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt;(source, originService, destinationService);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;destinationService&lt;/code&gt; 参数用于定点通知：&lt;code&gt;null&lt;/code&gt; 表示广播给所有服务，指定值（如 &lt;code&gt;user-service:**&lt;/code&gt;）则只发送给匹配的实例。&lt;/p&gt;&#xA;&lt;h3 id=&#34;3refreshlistener&#34;&gt;（3）RefreshListener&#xA;&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RefreshListener&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; ApplicationListener&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;RefreshRemoteApplicationEvent&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; RefreshScope refreshScope;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RefreshListener&lt;/span&gt;(RefreshScope refreshScope) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;refreshScope&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; refreshScope;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;onApplicationEvent&lt;/span&gt;(RefreshRemoteApplicationEvent event) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        refreshScope.&lt;span style=&#34;color:#a6e22e&#34;&gt;refreshAll&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;常见问题排查&#34;&gt;常见问题排查&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Bugs 刷新后配置未生效&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;@RefreshScope&lt;/code&gt; 是否标注在使用配置的 Bean 上（注意：@RefreshScope 只对加了该注解的 Bean 有效，其依赖的其他 Bean 不会重建）&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt; 的类只需标注 &lt;code&gt;@RefreshScope&lt;/code&gt; 即可刷新，但已经在使用的 Bean 不会自动重新注入——需要确保引用方也标注 @RefreshScope&lt;/li&gt;&#xA;&lt;li&gt;检查 Control Bus 端口（&lt;code&gt;spring.cloud.bus.id&lt;/code&gt;）是否在多个服务间唯一&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;事件未传播到其他服务&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查所有服务是否连接到同一个消息中间件实例（不同的 RabbitMQ vhost 或 Kafka topic 会导致隔离）&lt;/li&gt;&#xA;&lt;li&gt;检查 &lt;code&gt;spring.cloud.bus.destination&lt;/code&gt; 配置是否一致（默认 &lt;code&gt;springCloudBus&lt;/code&gt; 即可）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Bus refresh 导致启动过慢&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Bus 客户端启动时会连接到消息中间件，如果中间件不可用，启动会卡住。可通过 &lt;code&gt;spring.cloud.bus.enabled=false&lt;/code&gt; 禁用非必要实例的 Bus 功能&lt;/li&gt;&#xA;&lt;li&gt;建议配置 &lt;code&gt;spring.cloud.bus.env.enabled=true&lt;/code&gt;（默认开启），允许 Bus 端点只在特定 profile 下启用&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;RabbitMQ 配置正确但连接失败&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查防火墙和端口（5672 是 AMQP 端口，15672 是管理控制台——两者不要混淆）&lt;/li&gt;&#xA;&lt;li&gt;验证 RabbitMQ 的 vhost 和用户权限&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item></channel>
</rss>
