专栏首页码匠的流水账聊聊spring cloud的ConsulServer
原创

聊聊spring cloud的ConsulServer

本文主要研究一下spring cloud的ConsulServer

ConsulServer

spring-cloud-consul-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/discovery/ConsulServer.java

public class ConsulServer extends Server {
​
    private final MetaInfo metaInfo;
​
    private final HealthService service;
​
    private final Map<String, String> metadata;
​
    public ConsulServer(final HealthService healthService) {
        super(findHost(healthService), healthService.getService().getPort());
        this.service = healthService;
        this.metadata = ConsulServerUtils.getMetadata(this.service);
        this.metaInfo = new MetaInfo() {
            @Override
            public String getAppName() {
                return ConsulServer.this.service.getService().getService();
            }
​
            @Override
            public String getServerGroup() {
                return getMetadata().get("group");
            }
​
            @Override
            public String getServiceIdForDiscovery() {
                return null;
            }
​
            @Override
            public String getInstanceId() {
                return ConsulServer.this.service.getService().getId();
            }
        };
​
        setAlive(isPassingChecks());
    }
​
    @Override
    public MetaInfo getMetaInfo() {
        return this.metaInfo;
    }
​
    public HealthService getHealthService() {
        return this.service;
    }
​
    public Map<String, String> getMetadata() {
        return this.metadata;
    }
​
    public boolean isPassingChecks() {
        for (Check check : this.service.getChecks()) {
            if (check.getStatus() != Check.CheckStatus.PASSING) {
                return false;
            }
        }
        return true;
    }
​
}
  • ConsulServer继承了com.netflix.loadbalancer.Server;其构造器会调用isPassingChecks方法来setAlive,它通过HealthService来获取checks的状态

ConsulServerList

spring-cloud-consul-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/discovery/ConsulServerList.java

public class ConsulServerList extends AbstractServerList<ConsulServer> {
​
    private final ConsulClient client;
​
    private final ConsulDiscoveryProperties properties;
​
    private String serviceId;
​
    public ConsulServerList(ConsulClient client, ConsulDiscoveryProperties properties) {
        this.client = client;
        this.properties = properties;
    }
​
    protected ConsulClient getClient() {
        return this.client;
    }
​
    protected ConsulDiscoveryProperties getProperties() {
        return this.properties;
    }
​
    protected String getServiceId() {
        return this.serviceId;
    }
​
    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
        this.serviceId = clientConfig.getClientName();
    }
​
    @Override
    public List<ConsulServer> getInitialListOfServers() {
        return getServers();
    }
​
    @Override
    public List<ConsulServer> getUpdatedListOfServers() {
        return getServers();
    }
​
    private List<ConsulServer> getServers() {
        if (this.client == null) {
            return Collections.emptyList();
        }
        String tag = getTag(); // null is ok
        Response<List<HealthService>> response = this.client.getHealthServices(
                this.serviceId, tag, this.properties.isQueryPassing(),
                createQueryParamsForClientRequest(), this.properties.getAclToken());
        if (response.getValue() == null || response.getValue().isEmpty()) {
            return Collections.emptyList();
        }
        return transformResponse(response.getValue());
    }
​
    /**
     * Transforms the response from Consul in to a list of usable {@link ConsulServer}s.
     * @param healthServices the initial list of servers from Consul. Guaranteed to be
     * non-empty list
     * @return ConsulServer instances
     * @see ConsulServer#ConsulServer(HealthService)
     */
    protected List<ConsulServer> transformResponse(List<HealthService> healthServices) {
        List<ConsulServer> servers = new ArrayList<>();
        for (HealthService service : healthServices) {
            ConsulServer server = new ConsulServer(service);
            if (server.getMetadata()
                    .containsKey(this.properties.getDefaultZoneMetadataName())) {
                server.setZone(server.getMetadata()
                        .get(this.properties.getDefaultZoneMetadataName()));
            }
            servers.add(server);
        }
        return servers;
    }
​
    /**
     * This method will create the {@link QueryParams} to use when retrieving the services
     * from Consul. By default {@link QueryParams#DEFAULT} is used. In case a datacenter
     * is specified for the current serviceId {@link QueryParams#datacenter} is set.
     * @return an instance of {@link QueryParams}
     */
    protected QueryParams createQueryParamsForClientRequest() {
        String datacenter = getDatacenter();
        if (datacenter != null) {
            return new QueryParams(datacenter);
        }
        return QueryParams.DEFAULT;
    }
​
    protected String getTag() {
        return this.properties.getQueryTagForService(this.serviceId);
    }
​
    protected String getDatacenter() {
        return this.properties.getDatacenters().get(this.serviceId);
    }
​
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("ConsulServerList{");
        sb.append("serviceId='").append(this.serviceId).append('\'');
        sb.append(", tag=").append(getTag());
        sb.append('}');
        return sb.toString();
    }
​
}
  • ConsulServerList继承了com.netflix.loadbalancer.AbstractServerList;其getInitialListOfServers及getUpdatedListOfServers方法都会调用getServers方法;它通过ConsulClient.getHealthServices来获取指定serviceId的HealthService列表,然后通过transformResponse方法包装为ConsulServer列表

ConsulRibbonClientConfiguration

spring-cloud-consul-discovery-2.1.2.RELEASE-sources.jar!/org/springframework/cloud/consul/discovery/ConsulRibbonClientConfiguration.java

@Configuration
public class ConsulRibbonClientConfiguration {
​
    protected static final String VALUE_NOT_SET = "__not__set__";
​
    protected static final String DEFAULT_NAMESPACE = "ribbon";
​
    @Autowired
    private ConsulClient client;
​
    @Value("${ribbon.client.name}")
    private String serviceId = "client";
​
    public ConsulRibbonClientConfiguration() {
    }
​
    public ConsulRibbonClientConfiguration(String serviceId) {
        this.serviceId = serviceId;
    }
​
    @Bean
    @ConditionalOnMissingBean
    public ServerList<?> ribbonServerList(IClientConfig config,
            ConsulDiscoveryProperties properties) {
        ConsulServerList serverList = new ConsulServerList(this.client, properties);
        serverList.initWithNiwsConfig(config);
        return serverList;
    }
​
    @Bean
    @ConditionalOnMissingBean
    public ServerListFilter<Server> ribbonServerListFilter() {
        return new HealthServiceServerListFilter();
    }
​
    @Bean
    @ConditionalOnMissingBean
    public IPing ribbonPing() {
        return new ConsulPing();
    }
​
    @Bean
    @ConditionalOnMissingBean
    public ConsulServerIntrospector serverIntrospector() {
        return new ConsulServerIntrospector();
    }
​
    @PostConstruct
    public void preprocess() {
        setProp(this.serviceId, DeploymentContextBasedVipAddresses.key(), this.serviceId);
        setProp(this.serviceId, EnableZoneAffinity.key(), "true");
    }
​
    protected void setProp(String serviceId, String suffix, String value) {
        // how to set the namespace properly?
        String key = getKey(serviceId, suffix);
        DynamicStringProperty property = getProperty(key);
        if (property.get().equals(VALUE_NOT_SET)) {
            ConfigurationManager.getConfigInstance().setProperty(key, value);
        }
    }
​
    protected DynamicStringProperty getProperty(String key) {
        return DynamicPropertyFactory.getInstance().getStringProperty(key, VALUE_NOT_SET);
    }
​
    protected String getKey(String serviceId, String suffix) {
        return serviceId + "." + DEFAULT_NAMESPACE + "." + suffix;
    }
​
}
  • ConsulRibbonClientConfiguration注入了ribbonServerList,其创建的是ConsulServerList

小结

  • ConsulServer继承了com.netflix.loadbalancer.Server;其构造器会调用isPassingChecks方法来setAlive,它通过HealthService来获取checks的状态
  • ConsulServerList继承了com.netflix.loadbalancer.AbstractServerList;其getInitialListOfServers及getUpdatedListOfServers方法都会调用getServers方法;它通过ConsulClient.getHealthServices来获取指定serviceId的HealthService列表,然后通过transformResponse方法包装为ConsulServer列表
  • ConsulRibbonClientConfiguration注入了ribbonServerList,其创建的是ConsulServerList

doc

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 聊聊EurekaRibbonClientConfiguration

    spring-cloud-netflix-eureka-client-2.0.0.RELEASE-sources.jar!/org/springframewor...

    codecraft
  • 聊聊NacosNamingService的selectOneHealthyInstance

    本文主要研究一下NacosNamingService的selectOneHealthyInstance

    codecraft
  • 聊聊spring cloud的ConsulAutoConfiguration

    本文主要研究一下spring cloud的ConsulAutoConfiguration

    codecraft
  • 学习SpringMVC——说说视图解析器

      各位前排的,后排的,都不要走,咱趁热打铁,就这一股劲我们今天来说说spring mvc的视图解析器(不要抢,都有位子~~~)   相信大家在昨天那篇如何获取...

    JackieZheng
  • java学习:调用 java web service

    先写一个java的class:AwbModel(相当于要在web service中传输的实体对象) package webservicesample; pub...

    菩提树下的杨过
  • 利用Hadoop Mapreduce实现pv统计分析

    天策
  • 原 荐 SpringBoot 2.0 系列0

    石奈子
  • SpringBoot健康检查实现原理

    相信看完之前文章的同学都知道了SpringBoot自动装配的套路了,直接看spring.factories文件,当我们使用的时候只需要引入如下依赖

    Java学习录
  • 不了解这 12 个语法糖,别说你会 Java!

    本文从 Java 编译原理角度,深入字节码及 class 文件,抽丝剥茧,了解 Java 中的语法糖原理及用法,帮助大家在学会如何使用 Java 语法糖的同时,...

    Java技术江湖
  • Java之面向对象例子(二)

    定义一个Book类,在定义一个JavaBook类继承他 //book类 package com.hanqi.maya.model; public class B...

    二十三年蝉

扫码关注云+社区

领取腾讯云代金券