深入理解 DiscoveryClient

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();
		}

	}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值