Spring Cloud Commons 提供的抽象
一开始 服务注册和客户发现抽象 都在DiscoveryClient 随着版本的变迁 服务注册被抽离出来
服务注册抽象
- 从 DiscoveryClient 中抽离出了 ServiceRegistry 抽象 作为服务注册抽象
客户发现抽象
-
DiscoveryClient 抽象 负责了 客户发现抽象
• 通过 @EnableDiscoveryClient 注解 去做服务的发现 -
提供了 LoadBalancerClient 负载均衡 抽象
自动向 Eureka 服务端注册
ServiceRegistry
-
使用 EurekaServiceRegistry 做Eureka 服务的注册
-
在 EurekaRegistration 保存注册信息 client 相关的内容
自动配置
-
EurekaClientAutoConfiguration
-
EurekaAutoServiceRegistration
• 通过 SmartLifecycle 实现 是spring当中 生命管理周期的一步
做了一个自动的waiter-service向 Eureka 注册的动作
源码(以Eureka为例)
ServiceRegistry
public interface ServiceRegistry<R extends Registration> {
void register(R registration); //注册方法(重要)
void deregister(R registration);//取消注册方法(重要)
void close();//关闭方法
void setStatus(R registration, String status);//设置状态
<T> T getStatus(R registration);//获取状态
}
EurekaServiceRegistry
public class EurekaServiceRegistry implements ServiceRegistry<EurekaRegistration> {
private static final Log log = LogFactory.getLog(EurekaServiceRegistry.class);
public EurekaServiceRegistry() {
}
public void register(EurekaRegistration reg) {
this.maybeInitializeClient(reg); //取得EurekaRegistration 做一个初始化
if (log.isInfoEnabled()) {
log.info("Registering application " + reg.getApplicationInfoManager().getInfo().getAppName() + " with eureka with status " + reg.getInstanceConfig().getInitialStatus());
}
reg.getApplicationInfoManager().setInstanceStatus(reg.getInstanceConfig().getInitialStatus());//设置实例的一个状态
reg.getHealthCheckHandler().ifAvailable((healthCheckHandler) -> {
reg.getEurekaClient().registerHealthCheck(healthCheckHandler);
});//如果有healthCheckHandler 就去注册一下healthCheckHandler
}
private void maybeInitializeClient(EurekaRegistration reg) {
reg.getApplicationInfoManager().getInfo();
reg.getEurekaClient().getApplications();
}
public void deregister(EurekaRegistration reg) {
if (reg.getApplicationInfoManager().getInfo() != null) {
if (log.isInfoEnabled()) {
log.info("Unregistering application " + reg.getApplicationInfoManager().getInfo().getAppName() + " with eureka with status DOWN");
}
reg.getApplicationInfoManager().setInstanceStatus(InstanceStatus.DOWN);//将状态设置为了down
}
}
public void setStatus(EurekaRegistration registration, String status) {
InstanceInfo info = registration.getApplicationInfoManager().getInfo();
if ("CANCEL_OVERRIDE".equalsIgnoreCase(status)) {
registration.getEurekaClient().cancelOverrideStatus(info);
} else {
InstanceStatus newStatus = InstanceStatus.toEnum(status);
registration.getEurekaClient().setStatus(newStatus, info);
}
}
public Object getStatus(EurekaRegistration registration) {
String appname = registration.getApplicationInfoManager().getInfo().getAppName();
String instanceId = registration.getApplicationInfoManager().getInfo().getId();
InstanceInfo info = registration.getEurekaClient().getInstanceInfo(appname, instanceId);
HashMap<String, Object> status = new HashMap();
if (info != null) {
status.put("status", info.getStatus().toString());
status.put("overriddenStatus", info.getOverriddenStatus().toString());
} else {
status.put("status", InstanceStatus.UNKNOWN.toString());
}
return status;
}
public void close() {
}
}
EurekaAutoServiceRegistration
public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered, SmartApplicationListener {
private static final Log log = LogFactory.getLog(EurekaAutoServiceRegistration.class);
private AtomicBoolean running = new AtomicBoolean(false);
private int order = 0;
private AtomicInteger port = new AtomicInteger(0);
private ApplicationContext context;
private EurekaServiceRegistry serviceRegistry;
private EurekaRegistration registration;
public EurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry serviceRegistry, EurekaRegistration registration) {
this.context = context;
this.serviceRegistry = serviceRegistry;
this.registration = registration;
}
public void start() {
if (this.port.get() != 0) {
if (this.registration.getNonSecurePort() == 0) {
this.registration.setNonSecurePort(this.port.get());
}
if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
this.registration.setSecurePort(this.port.get());
}
}
//检测port
if (!this.running.get() && this.registration.getNonSecurePort() > 0) {//如果没有启动过 并且 非安全接口大于0
this.serviceRegistry.register(this.registration);//调用serviceRegistry 将自己的registration 注册上去
this.context.publishEvent(new InstanceRegisteredEvent(this, this.registration.getInstanceConfig()));// 发布一个事件
this.running.set(true);// 设置running状态为 true 下一次 当进入start()方法之后 this.running.get() 取为true 就不会再进行一次注册了
}
}
public void stop() {
this.serviceRegistry.deregister(this.registration);//取消注册
this.running.set(false);//设置running状态为 flase
}
public boolean isRunning() {
return this.running.get();
}
public int getPhase() {
return 0;
}
public boolean isAutoStartup() {
return true;
}
public void stop(Runnable callback) {
this.stop();
callback.run();
}
public int getOrder() {
return this.order;
}
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return WebServerInitializedEvent.class.isAssignableFrom(eventType) || ContextClosedEvent.class.isAssignableFrom(eventType);
}
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof WebServerInitializedEvent) {
this.onApplicationEvent((WebServerInitializedEvent)event);
} else if (event instanceof ContextClosedEvent) {
this.onApplicationEvent((ContextClosedEvent)event);
}
}
public void onApplicationEvent(WebServerInitializedEvent event) {
int localPort = event.getWebServer().getPort();
if (this.port.get() == 0) {
log.info("Updating port to " + localPort);
this.port.compareAndSet(0, localPort);
this.start();
}
}
public void onApplicationEvent(ContextClosedEvent event) {
if (event.getApplicationContext() == this.context) {
this.stop();
}
}
}
DiscoveryClient
public interface DiscoveryClient extends Ordered {
int DEFAULT_ORDER = 0;
String description();//提供描述信息
List<ServiceInstance> getInstances(String serviceId);//根据serviceId 找到我对应的ServiceInstance 如果传的是 waiter-server 那就返回所有 waiter-server 的实例
List<String> getServices();//获取所有的服务
default int getOrder() {
return 0;
}
}
EurekaDiscoveryClient
public class EurekaDiscoveryClient implements DiscoveryClient {
/**
* Client description {@link String}.
*/
public static final String DESCRIPTION = "Spring Cloud Eureka Discovery Client";
private final EurekaClient eurekaClient;
private final EurekaClientConfig clientConfig;
@Deprecated
public EurekaDiscoveryClient(EurekaInstanceConfig config, EurekaClient eurekaClient) {
this(eurekaClient, eurekaClient.getEurekaClientConfig());
}
public EurekaDiscoveryClient(EurekaClient eurekaClient,
EurekaClientConfig clientConfig) {
this.clientConfig = clientConfig;
this.eurekaClient = eurekaClient;
}
@Override
public String description() {
return DESCRIPTION;
}
@Override
public List<ServiceInstance> getInstances(String serviceId) {
List<InstanceInfo> infos = this.eurekaClient.getInstancesByVipAddress(serviceId,
false);// 根据serviceId 做一个查找 通过eurekaClient 去找到infos 加入list进去
List<ServiceInstance> instances = new ArrayList<>();
for (InstanceInfo info : infos) {
instances.add(new EurekaServiceInstance(info));
}
return instances;
}
@Override
public List<String> getServices() {
Applications applications = this.eurekaClient.getApplications();
if (applications == null) {
return Collections.emptyList();
}
List<Application> registered = applications.getRegisteredApplications();
List<String> names = new ArrayList<>();
for (Application app : registered) {
if (app.getInstances().isEmpty()) {
continue;
}
names.add(app.getName().toLowerCase());
}
return names;
}
@Override
public int getOrder() {
return clientConfig instanceof Ordered ? ((Ordered) clientConfig).getOrder()
: DiscoveryClient.DEFAULT_ORDER;
}
/**
* An Eureka-specific {@link ServiceInstance} implementation.
*/
public static class EurekaServiceInstance implements ServiceInstance {
private InstanceInfo instance;
public EurekaServiceInstance(InstanceInfo instance) {
Assert.notNull(instance, "Service instance required");
this.instance = instance;
}
public InstanceInfo getInstanceInfo() {
return instance;
}
@Override
public String getInstanceId() {
return this.instance.getId();
}
@Override
public String getServiceId() {
return this.instance.getAppName();
}
@Override
public String getHost() {
return this.instance.getHostName();
}
@Override
public int getPort() {
if (isSecure()) {
return this.instance.getSecurePort();
}
return this.instance.getPort();
}
@Override
public boolean isSecure() {
// assume if secure is enabled, that is the default
return this.instance.isPortEnabled(SECURE);
}
@Override
public URI getUri() {
return DefaultServiceInstance.getUri(this);
}
@Override
public Map<String, String> getMetadata() {
return this.instance.getMetadata();
}
}
}