自动配置
在spring-cloud-consul-discovery.jar!/META-INF/spring.factories中,有如下配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration,\
org.springframework.cloud.consul.discovery.configclient.ConsulConfigServerAutoConfiguration,\
org.springframework.cloud.consul.serviceregistry.ConsulAutoServiceRegistrationAutoConfiguration,\
org.springframework.cloud.consul.serviceregistry.ConsulServiceRegistryAutoConfiguration,\
org.springframework.cloud.consul.discovery.ConsulDiscoveryClientConfiguration
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.consul.discovery.configclient.ConsulDiscoveryClientConfigServiceBootstrapConfiguration
后面我们将逐一分析这些配置带来的效果。
服务注册
服务注册要解决一个经典的问题
- 我是谁
- 我在哪
- 我要去向何方
在分布式服务中,一个服务通常有多个实例,这时候需要分别申明服务和实例,以便确认主体,合并不同实例。服务声明就是告诉consul server“我是谁”,ConsulAutoRegistration定制了包括服务名称serviceName和服务唯一标识instanceID的规则。
服务注册的目的是让别的服务能够使用,通常我们访问一个http服务是通过host:port这样的uri定位。host又分为ip和域名两种类型。一个springboot服务是如何知道“我在哪”呢?spring的InetUtils使用了jdk的java.net.NetworkInterface网络接口获得当前服务IP和hostname,具体原理可以参考附录中的“java中的getHostname”。而port则是通过WebServerInitializedEvent.getWebServer(). getPort()获得。
consul server的地址可以直接通过配置获得,spring cloud通过AgentConsulClient代理了对 consul server的请求。
服务初始注册
1. ConsulAutoServiceRegistrationListener.onApplicationEvent(ApplicationEvent)
2. ConsulAutoServiceRegistration.start()
3. ConsulAutoServiceRegistration.register()
4. AbstractAutoServiceRegistration.register()
5. ConsulServiceRegistry.register(Registration)
6. ConsulClient.agentServiceRegister(NewService,String)
7. AgentConsulClient.agentServiceRegister(NewService,String)
8. ConsulRawClient.makePutRequest()
- ConsulAutoServiceRegistrationListener监听服务启动事件WebServerInitializedEvent,执行服务注册。在第一步中调用了这样一个代码:this.autoServiceRegistration.setPortIfNeeded(event.getWebServer().getPort()),此处通过jdk的CAS机制实现了防止重复设置端口和并发操作。
//ConsulAutoServiceRegistration
private AtomicInteger port = new AtomicInteger(0);
void setPortIfNeeded(int port) {
getPort().compareAndSet(0, port);
}
- ConsulServiceRegistry是服务注册,销毁等业务功能的流程控制类。