以下是Spring Cloud Bus的例子和完整攻略。
Spring Cloud Bus简介
Spring Cloud Bus是Spring Cloud家族中的一个基于消息中间件构建的分布式应用事件传播机制。通过Spring Cloud Bus,我们可以轻松的实现服务之间的通信和事件的传递,从而实现基于消息驱动架构(MDA)的微服务应用。
Spring Cloud Bus支持两种消息中间件协议:RabbitMQ和Kafka。Spring Cloud Bus默认的协议是RabbitMQ,因此只需要在pom.xml文件中引入如下代码即可:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
Spring Cloud Bus的使用非常简单,只需要在应用启动时添加@EnableBus
注解即可:
@SpringBootApplication
@EnableBus
public class BusApplication {
public static void main(String[] args) {
SpringApplication.run(BusApplication.class, args);
}
}
Spring Cloud Bus实例代码
下面我们来看看Spring Cloud Bus的两个实例代码:
示例1:动态刷新配置
在微服务应用中,通常需要配置中心来管理各个服务的配置信息。Spring Cloud Config是常用的配置中心组件之一。但是,如果某个服务的配置发生变化,我们还需要手动去重启应用。如何实现在某个服务的配置信息变化时,自动通知其他服务?
答案就是采用Spring Cloud Bus,我们可以利用Spring Cloud Bus的特性来实现配置文件的自动更新,而无需手动重启服务。
首先,我们需要在应用中配置Bus Refresh Endpoint来实现在某个应用进行了配置文件变更时,其他应用能够自动更新。
在项目的application.properties或者application.yml文件中,添加如下配置:
management:
endpoints:
web:
exposure:
include: bus-refresh
上述配置中,我们开启了bus-refresh端点的控制,使得其他的服务可以通过调用/bus-refresh端点来刷新服务的配置。
接下来,在我们需要刷新服务配置的地方,通过发出POST请求/bus/refresh来刷新服务的配置,如下所示:
@RestController
public class ViewController {
@Autowired
private Environment environment;
@PostMapping("/refreshEnv")
public String refreshEnv(String key, String value) {
environment.getPropertySources().addFirst(new MapPropertySource("custom",
Collections.singletonMap(key, value)));
return "refresh success";
}
}
在上述代码中,我们利用Environment对象的getPropertySources()方法获取到配置文件的全部属性,然后将需要更新的配置项添加进去即可。
最后,我们可以通过使用postman等工具对refreshEnv进行测试。
在修改配置后,我们调用http://localhost:8080/post?key=foobar&value=foo
,可以看到控制台会输出如下日志信息:
2019-06-26 14:30:08.287 INFO 16588 --- [nio-8080-exec-1] c.c.b.controller.ViewController : refresh success
2019-06-26 14:30:08.319 INFO 16588 --- [hread: rabbit@localhost:5672] o.s.c.bus.spring.CloudBusBridge : /refresh sent to destination(s): myapp:**, anotherapp:**
最后,在其他的服务中也添加配置文件,通过使用@RefreshScope注解实现配置文件的自动刷新。
@RefreshScope
@RestController
public class HelloController {
@Value("${server.port}")
String port;
@Value("${test.name}")
private String testName;
@RequestMapping("/hi")
public String home() {
return "hi " + testName + ",i am from port:" + port;
}
}
这样,当我们发起POST请求时,其他的服务的配置文件也会自动刷新,从而实现了基于消息驱动的配置管理。
示例2:服务实例数量统计
在微服务应用中,服务实例数量的状态信息非常重要。
我们可以通过Spring Cloud Bus将服务实例数量的状态信息发送到消息总线上,从而实现任意一个服务实例都能够获取其他服务实例的状态信息。
下面是一个统计服务实例数量的实例代码。
在pom.xml中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
其中,spring-boot-starter-actuator是Spring Boot应用的指标展示组件,该依赖主要是负责将应用的指标(Metrics)数据暴露到Spring Boot内置的HTTP端点中,便于应用的健康状况监控。
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class BusApplication {
public static void main(String[] args) {
SpringApplication.run(BusApplication.class, args);
}
@GetMapping("/ping")
public String ping() {
return "pong";
}
}
上述代码中,我们通过@EnableDiscoveryClient注解开启服务注册和发现的功能,然后在控制器中添加@GetMapping("/ping")来实现测试服务是否可用。
接下来,我们需要修改Eureka Server的配置文件,增加Metrics HTTP端口的监听。
在eureka-server的application.yml或者application.properties文件中添加如下配置:
eureka:
instance:
metadata-map:
management.port: ${server.port}
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 60000
client:
register-with-eureka: false
fetch-registry: false
management:
endpoints:
web:
exposure:
include: metrics
metrics:
enable:
在上述代码中,主要我们通过在application.yml文件中修改management端口开启指标暴露,从而实现了应用的指标监控。
接下来,我们通过定义自定义的Endpoint来统计当前服务实例的数量:
@Component
public class InstanceCountEndpoint extends AbstractEndpoint<Long> {
@Autowired
private DiscoveryClient discoveryClient;
public InstanceCountEndpoint() {
super("instanceCountEndpoint");
}
@Override
public Long invoke() {
List<String> services = discoveryClient.getServices();
Map<String, List<ServiceInstance>> serviceMap = new LinkedHashMap<>(services.size());
services.forEach(s -> serviceMap.put(s, discoveryClient.getInstances(s)));
return serviceMap.values().stream().flatMap(Collection::stream).count();
}
}
上述代码中,我们通过Endpoint来统计服务实例的数量,其中通过DiscoveryClient对象获取当前已注册的服务列表,使用流式API将列表转换为
最后,我们在应用启动类中添加@EnableConfigurationProperties注解,并在application.yml配置文件中添加InstanceCountMetric的配置。
@SpringBootApplication
@EnableDiscoveryClient
@RestController
@EnableConfigurationProperties(InstanceCountMetric.class)
public class BusApplication {
@Autowired
private InstanceCountMetric instanceCountMetric;
public static void main(String[] args) {
SpringApplication.run(BusApplication.class, args);
}
@GetMapping("/ping")
public String ping() {
return "pong";
}
@GetMapping("/instanceCount")
public String instanceCount() {
return String.valueOf(instanceCountMetric.getCount());
}
}
在上述代码中,我们将InstanceCountMetric注入到应用中,并在@GetMapping("/instanceCount")API的处理方法中使用该对象获取实例数量。
到这里,我们已经完成了Spring Cloud Bus实例代码的编写,可以通过localhost:8762/instanceCount接口来获取当前注册中心中服务的实例数量。
总之,Spring Cloud Bus是实现微服务消息机制的重要组件,可以为我们实现微服务应用的通信和事件传递机制。在实际应用中,我们可以通过Spring Cloud Bus实现各种应用场景。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringCloud之消息总线Spring Cloud Bus实例代码 - Python技术站