Gateway Ribbon Nacos的那點事


前言

Gateway  Ribbon  Nacos分別屬於不同組織開發的框架,但是能共同服務於微服務框架中,它們是如何配合的呢

Gateway

1.在自動配置類GatewayDiscoveryClientAutoConfiguration中有一段代碼

    @Bean
        @ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")
        public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(
                ReactiveDiscoveryClient discoveryClient,
                DiscoveryLocatorProperties properties) {
            return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
        }

當spring.cloud.gateway.discovery.locator.enabled為true,這段代碼會從ReactiveDiscoveryClient的實現類中獲取服務名稱列表封裝成路由定義,而Nacos中有對應的實現類為NacosReactiveDiscoveryClient,這是它們的聯系點之一

2.當外部請求進來時,例如https://host/服務名/xxx,會經過一個全局過濾器,為LoadBalancerClientFilter,這個過濾器的作用是將url的服務名稱改成真正服務所在的ip,里面有段關鍵代碼是

protected ServiceInstance choose(ServerWebExchange exchange) {
        return loadBalancer.choose(
                ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
    }

上面起作用的是loadBalancer,對應的類型是LoadBalancerClient,這個是gateway框架定義的接口,真正實現類是Ribbon的RibbonLoadBalancerClient,這是gateway和ribbon的關聯點

Ribbon

再來看看RibbonLoadBalancerClient的choose方法

public ServiceInstance choose(String serviceId, Object hint) {
        Server server = getServer(getLoadBalancer(serviceId), hint);
        if (server == null) {
            return null;
        }
        return new RibbonServer(serviceId, server, isSecure(server, serviceId),
                serverIntrospector(serviceId).getMetadata(server));
    }

上面關鍵代碼是getLoadBalancer(serviceId),如下

protected ILoadBalancer getLoadBalancer(String serviceId) {
        return this.clientFactory.getLoadBalancer(serviceId);
    }

這段代碼目的是取出ILoadBalancer的實現類,其為ZoneAwareLoadBalancer,而它又是繼承DynamicServerListLoadBalancer,構造函數如下

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping,
                                         ServerList<T> serverList, ServerListFilter<T> filter,
                                         ServerListUpdater serverListUpdater) {
        super(clientConfig, rule, ping);
        this.serverListImpl = serverList;
        this.filter = filter;
        this.serverListUpdater = serverListUpdater;
        if (filter instanceof AbstractServerListFilter) {
            ((AbstractServerListFilter) filter).setLoadBalancerStats(getLoadBalancerStats());
        }
        restOfInit(clientConfig);
    }

上面的構造函數會自動注入類型ServerList<T>的serverList,而nacos的NacosServerList實現了其接口,這里就是ribbon和nacos的連接點.

nacos

再來看看nacos什么時候提供了NacosServerList,看下面配置類

@Configuration(proxyBeanMethods = false)
@ConditionalOnRibbonNacos
public class NacosRibbonClientConfiguration {

    @Autowired
    private PropertiesFactory propertiesFactory;

    @Bean
    @ConditionalOnMissingBean
    public ServerList<?> ribbonServerList(IClientConfig config,
            NacosDiscoveryProperties nacosDiscoveryProperties) {
        if (this.propertiesFactory.isSet(ServerList.class, config.getClientName())) {
            ServerList serverList = this.propertiesFactory.get(ServerList.class, config,
                    config.getClientName());
            return serverList;
        }
        NacosServerList serverList = new NacosServerList(nacosDiscoveryProperties);
        serverList.initWithNiwsConfig(config);
        return serverList;
    }

    @Bean
    @ConditionalOnMissingBean
    public NacosServerIntrospector nacosServerIntrospector() {
        return new NacosServerIntrospector();
    }

}

在此配置類中,nacos提供了NacosServerList.另外,NacosServerList里面有方法getServers

private List<NacosServer> getServers() {
        try {
            String group = discoveryProperties.getGroup();
            List<Instance> instances = discoveryProperties.namingServiceInstance()
                    .selectInstances(serviceId, group, true);
            return instancesToServerList(instances);
        }
        catch (Exception e) {
            throw new IllegalStateException(
                    "Can not get service instances from nacos, serviceId=" + serviceId,
                    e);
        }
    }

selectInstances方法主要邏輯是向nacosserver發起http請求,獲取服務的地址列表.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM