我们可以直接通过 uri 配置,也可以具体配置其中的 host,port 和 isSecure,两者是等价的。例如:
spring: cloud: discovery: client: # SimpleDiscoveryClient与SimpleReactiveDiscoveryClient的配置 simple: instances: #微服务1 service1: #实例1 - host: instance1 #地址 port: 8080 #端口
等价于
spring: cloud: discovery: client: # SimpleDiscoveryClient与SimpleReactiveDiscoveryClient的配置 simple: instances: #微服务1 service1: #实例1 - uri: http://instance1:8080
instanceId 不一定需要指定,serviceId 会根据实例配置的上一级取,就算自己配置了,例如:
spring: cloud: discovery: client: # SimpleDiscoveryClient与SimpleReactiveDiscoveryClient的配置 simple: instances: #微服务1 service1: #实例1 - host: instance1 #地址 port: 8080 #端口 serviceId: service2 #无效,实际还是service1
serviceId 还是实际合理的那个,也就是 service1。
这些机制在后面的源码分析就会理解了。 我们的测试代码会用到 Spring Boot 的事件机制,也就是在 ApplicationContext 到某一生命周期的时候,这些事件会被发布出来,由实现了对应事件的ApplicationListener
接口的 Bean 消费,Spring boot 中,事件主要包括:
ApplicationStartingEvent
:这个是spring boot应用一开始启动时,发出的事件,只是用来标识,应用开始启动了,一般没什么用ApplicationEnvironmentPreparedEvent
:这个是在创建好Environment(通过上下文配置,判断到底创建StandardServletEnvironment(针对Servlet环境),StandardReactiveWebEnvironment(针对Reactive环境)还是StandardEnvironment(针对无servlet环境))之后发出的事件。ApplicationContextInitializedEvent
: 这个是在创建好Context并调用ApplicationContextInitializer初始化context之后发布这个事件,在加载bean信息之前ApplicationPreparedEvent
:加载bean信息之后,但是还没有创建bean的时候,发步这个事件。这个事件是和调用ApplicationContextAware
设置ApplicationContext一起进行的,可以看出,setApplicationContext方法里面不能去获取bean,因为bean可能还没有初始化完成ApplicationStartedEvent
: 加载初始化各种需要的bean并依赖注入之后,在运行ApplicationRunner
做一些用户自定义的初始化操作之前,会发布这个事件。ApplicationReadyEvent
:运行ApplicationRunner
做一些用户自定义的初始化操作之后,会发布这个事件。
我们使用ApplicationReadyEvent
的ApplicationListener
确保所有的DiscoveryClient
都初始化完成并可以使用作为测试类。
编写测试类: TestSimpleDiscoveryClient
/** * 通过消费 ApplicationReadyEvent 来确保 DiscoveryClient 初始化完成并可用 */ @Slf4j @Component public class TestSimpleDiscoveryClient implements ApplicationListener<ApplicationReadyEvent> { /** * 初始化的方法返回类型是 DiscoveryClient 并且不是 Primary,这里只能通过 @Resource 自动装载不能通过 @Autowired * 这里不排除以后返回类型修改为 SimpleDiscoveryClient 的可能性 * @see org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration */ @Resource private SimpleDiscoveryClient simpleDiscoveryClient; @Override public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) { List<String> services = simpleDiscoveryClient.getServices(); services.forEach(serviceId -> { log.info("{}: {}", serviceId, simpleDiscoveryClient.getInstances(serviceId)); }); } }
TestSimpleReactiveDiscoveryClient
/** * 通过消费 ApplicationReadyEvent 来确保 DiscoveryClient 初始化完成并可用 */ @Slf4j @Component public class TestSimpleReactiveDiscoveryClient implements ApplicationListener<ApplicationReadyEvent> { @Autowired private SimpleReactiveDiscoveryClient simpleReactiveDiscoveryClient; @Override public void onApplicationEvent(ApplicationReadyEvent event) { simpleReactiveDiscoveryClient.getServices().subscribe(serviceId -> { simpleReactiveDiscoveryClient.getInstances(serviceId).collect(Collectors.toList()).subscribe(serviceInstances -> { log.info("{}: {}", serviceId, serviceInstances); }); }); } }
@SpringBootApplication public class DiscoveryClientMain { public static void main(String[] args) { SpringApplication.run(DiscoveryClientMain.class, args); } }
启动后,可以看到日志:
2021-01-19 09:38:05.646 INFO 6168 --- [ main] .h.s.c.i.s.d.s.TestSimpleDiscoveryClient : service2: [DefaultServiceInstance{instanceId='instance3:80', serviceId='service2', host='instance3', port=80, secure=false, metadata={}}, DefaultServiceInstance{instanceId='null', serviceId='service2', host='instance4', port=8080, secure=true, metadata={}}] 2021-01-19 09:38:05.647 INFO 6168 --- [ main] .h.s.c.i.s.d.s.TestSimpleDiscoveryClient : service1: [DefaultServiceInstance{instanceId='instance:8080', serviceId='service1', host='instance1', port=8080, secure=false, metadata={}}, DefaultServiceInstance{instanceId='null', serviceId='service1', host='instance2', port=443, secure=true, metadata={}}] 2021-01-19 09:38:05.913 INFO 6168 --- [ main] .s.d.s.TestSimpleReactiveDiscoveryClient : service2: [DefaultServiceInstance{instanceId='instance3:80', serviceId='service2', host='instance3', port=80, secure=false, metadata={}}, DefaultServiceInstance{instanceId='null', serviceId='service2', host='instance4', port=8080, secure=true, metadata={}}] 2021-01-19 09:38:05.913 INFO 6168 --- [ main] .s.d.s.TestSimpleReactiveDiscoveryClient : service1: [DefaultServiceInstance{instanceId='instance:8080', serviceId='service1', host='instance1', port=8080, secure=false, metadata={}}, DefaultServiceInstance{instanceId='null', serviceId='service1', host='instance2', port=443, secure=true, metadata={}}]