zoukankan      html  css  js  c++  java
  • 通过ribbon 根据服务名获取所有服务实例的IP和端口列表

    代码使用SpringCloud版本E3

    业务场景:

    今天遇到一个业务场景,要求根据服务名获取当前微服务集群中所有的对应服务实例的IP和端口,通过分析源码推算出了写法。

    原理简述:

    如果代码中引入了spring-cloud-netflix-core(版本1.4.4.RELEASE),则在代码初始化的时候,会通过RibbonAutoConfiguration类创建一个SpringClientFactory的bean,通过该bean可以获取服务实例的IP和端口列表。

    代码中的 DomainExtractingServerList对象 是 DynamicServerListLoadBalancer 类中的属性,该属性保存的是全量的服务实例,不过却是私有的,所以只能通过反射来获取了。

    具体代码:

    package com.liuyx;
    
    import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
    import com.netflix.loadbalancer.ILoadBalancer;
    import com.netflix.loadbalancer.Server;
    import com.netflix.loadbalancer.ServerList;
    import com.netflix.niws.loadbalancer.DiscoveryEnabledServer;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
    import org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList;
    import org.springframework.context.ApplicationContext;
    
    import java.lang.reflect.Field;
    import java.util.List;
    
    /**
     * Created by liu.yuxiang on 2017/10/12.
     */
    @SpringBootApplication//(exclude = {ConfigClientAutoConfiguration.class})
    public class PortalZuulApplication {
    
    
        public static void main(String[] args) {
            ApplicationContext ctx = new SpringApplicationBuilder(PortalZuulApplication.class).web(true).run(args);
    
            SpringClientFactory springClientFactory = ctx.getBean(SpringClientFactory.class);
            ILoadBalancer loadBalancer = springClientFactory.getLoadBalancer("[服务名]");
            List<Server> servers = loadBalancer.getReachableServers();
            for(Server server:servers){
                //如果服务有设置zone,此处获取的可能并不是所有的实例
                System.out.println("---:"+server.getHostPort());
            }
    
            DynamicServerListLoadBalancer<DiscoveryEnabledServer> dynamicServerListLoadBalancer = (DynamicServerListLoadBalancer)loadBalancer;
    
            ServerList<DiscoveryEnabledServer> serverListImpl = dynamicServerListLoadBalancer.getServerListImpl();
    
            DomainExtractingServerList domainExtractingServerList1 = (DomainExtractingServerList) serverListImpl;
    
            try {
                Field field = domainExtractingServerList1.getClass().getDeclaredField("list");
                field.setAccessible(true);
                ServerList<DiscoveryEnabledServer> list = (ServerList<DiscoveryEnabledServer>)field.get(domainExtractingServerList1);
    
                for(DiscoveryEnabledServer server:list.getUpdatedListOfServers()){
                    //此处获取的是所有的实例
                    System.out.println("%%%:"+server.getHostPort());
                }
    
                /*for(DiscoveryEnabledServer server:list.getInitialListOfServers()){
                    System.out.println("+++:"+server.getHostPort());
                }*/
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    代码中的"[服务名]"请换成你自己的。

    因项目中使用了zone(即 eureka.instance.metadata-map.zone=xxx),所以只能通过反射,才能获取真正的所有服务实例,否则只能获取zone为xxx的服务实例。

    如果还不明白,参看 区域亲和

  • 相关阅读:
    JavaScript的作用域和块级作用域概念理解
    正则表达式中组的理解
    正则表达式的字符组取反(负值字符集合/范围)^必须出现在起始位置
    利用TortoiseGit(小乌龟)将项目上传至GitHub网站
    (.Net) NLog 记录日志功能
    关于网站中引用COM组件的部署问题
    备份与还原ORACLE数据库(通过CMD命令执行)
    C# Task中的Func, Action, Async与Await的使用
    ASP.NET WebAPI 项目示例(增删改查)
    .NET内存泄漏(之 静态事件)
  • 原文地址:https://www.cnblogs.com/flying607/p/9560159.html
Copyright © 2011-2022 走看看