zoukankan      html  css  js  c++  java
  • 六、eureka客户端自动注册服务

    所有文章

    https://www.cnblogs.com/lay2017/p/11908715.html

    正文

    上一篇文章,我们稍微了解了一下eureka客户端是如何自动配置的,配置了哪些东西。在自动配置的时候会产生一个负责自动注册的Bean,也就是

    @Bean
    @ConditionalOnBean(AutoServiceRegistrationProperties.class)
    @ConditionalOnProperty(
            value = "spring.cloud.service-registry.auto-registration.enabled",
            matchIfMissing = true)
    public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(
            ApplicationContext context, EurekaServiceRegistry registry,
            EurekaRegistration registration) {
        return new EurekaAutoServiceRegistration(context, registry, registration);
    }

    所以,我们打开EurekaAutoServiceRegistration看看

    public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered, SmartApplicationListener {
    
        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;
        }
    
        @Override
        public void start() {
            // ...
    
            if (!this.running.get() && this.registration.getNonSecurePort() > 0) {
    
                // 调用注册
                this.serviceRegistry.register(this.registration);
    
                this.context.publishEvent(new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig()));
    
                this.running.set(true);
            }
        }
    
    }

    注册任务被委托给了serviceRegistry来做,跟进register方法

    @Override
    public void register(EurekaRegistration reg) {
        maybeInitializeClient(reg);
    
        // ...
    
        reg.getApplicationInfoManager().setInstanceStatus(reg.getInstanceConfig().getInitialStatus());
    
        reg.getHealthCheckHandler().ifAvailable(healthCheckHandler -> reg.getEurekaClient().registerHealthCheck(healthCheckHandler));
    }

    调用了eurekaClient原始的registerhealthCheck方法,跟进它

    @Override
    public void registerHealthCheck(HealthCheckHandler healthCheckHandler) {
        if (instanceInfo == null) {
            logger.error("Cannot register a healthcheck handler when instance info is null!");
        }
        if (healthCheckHandler != null) {
            // 注册心跳检查处理器
            this.healthCheckHandlerRef.set(healthCheckHandler);
            
            // schedule an onDemand update of the instanceInfo when a new healthcheck handler is registered
            if (instanceInfoReplicator != null) {
                instanceInfoReplicator.onDemandUpdate();
            }
        }
    }

    心跳检查处理器被设置为了成员变量,执行的核心逻辑被托付给了onDemandUpdate方法,跟进它

    public boolean onDemandUpdate() {
        if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {
            if (!scheduler.isShutdown()) {
                scheduler.submit(new Runnable() {
                    @Override
                    public void run() {
                        // ...
    
                        InstanceInfoReplicator.this.run();
                    }
                });
                return true;
            } else {
                // ... 
            }
        } else {
            // ...
        }
    }

    单线程异步执行了当前类的run方法,进入run方法

    public void run() {
        try {
            // 刷新实例信息
            discoveryClient.refreshInstanceInfo();
    
            Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
            if (dirtyTimestamp != null) {
                // 注册
                discoveryClient.register();
                instanceInfo.unsetIsDirty(dirtyTimestamp);
            }
        } catch (Throwable t) {
            // ...
        } finally {
            // 下一次延迟执行
            Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
            scheduledPeriodicRef.set(next);
        }
    }

    run方法每次执行都会刷新实例信息,然后调用register注册新的实例信息,最后发出下一次执行的延迟任务

    跟进register方法

    boolean register() throws Throwable {
        logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
        EurekaHttpResponse<Void> httpResponse;
        try {
            // 发出远程请求
            httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
        } catch (Exception e) {
            
        }
        
        return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
    }

    继续跟进register方法,发出了http请求,这里以jersey为例

    @Override
    public EurekaHttpResponse<Void> register(InstanceInfo info) {
        String urlPath = "apps/" + info.getAppName();
        ClientResponse response = null;
        try {
            Builder resourceBuilder = jerseyClient.resource(serviceUrl).path(urlPath).getRequestBuilder();
            addExtraHeaders(resourceBuilder);
            response = resourceBuilder
                    .header("Accept-Encoding", "gzip")
                    .type(MediaType.APPLICATION_JSON_TYPE)
                    .accept(MediaType.APPLICATION_JSON)
                    // 发出http请求
                    .post(ClientResponse.class, info);
            return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
        } finally {
            if (logger.isDebugEnabled()) {
                logger.debug("Jersey HTTP POST {}/{} with instance {}; statusCode={}", serviceUrl, urlPath, info.getId(),
                        response == null ? "N/A" : response.getStatus());
            }
            if (response != null) {
                response.close();
            }
        }
    }

    http请求将进入eureka服务端,注册实例信息有兴趣可以看看eureka服务端注册服务这篇。

    总结

    eureka客户端自动注册服务主要是将自动配置的时候拿到的实例信息通过http请求发送给eureka服务端,默认30秒会执行一次。

  • 相关阅读:
    配置Robot Framework 环境时如何查看wxPython是否成功安装
    win10系统同时安装python2.7和python3.6
    Python 统计不同url svn代码变更数
    JavaWeb之 Servlet执行过程 与 生命周期
    JavaWeb之Servlet:请求 与 响应
    webservice(基础)
    通过反射,给对象之间赋值
    用反射获取类中的属性值
    tree树形
    破解weblogic(数据库)密码
  • 原文地址:https://www.cnblogs.com/lay2017/p/11922673.html
Copyright © 2011-2022 走看看