Discovery

Discovery(https://github.com/Nepxion/Discovery)是一个基于spring cloud的,可以执行蓝绿,灰度,路由等功能的一个框架。 功能就是在一个服务在线上有多个版本存在的时候,可以通过指定不同的版本,让流量流向不同的版本。

大致的实现方式如下:

spring cloud本身提供了一些组件,比如feigin,discoveryclient ribbon,resttemple完成了服务的注册,发现,负载,调用,Discovery框架对这些实现进行了增强,比如通过spring的addBeanPostProcessor()

        //  所有 bean 都构造完之后调用
        applicationContext.getBeanFactory().addBeanPostProcessor(new InstantiationAwareBeanPostProcessorAdapter() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                // 如果是DiscoveryClient类型
                if (bean instanceof DiscoveryClient) {
                    // 获取类型
                    DiscoveryClient discoveryClient = (DiscoveryClient) bean;
                    // 将类型作为参数传入, 这里很重要, 在这里就完成了适配。
                    return new DiscoveryClientDecorator(discoveryClient, applicationContext);
                } else {
                    return afterInitialization(applicationContext, bean, beanName);
                }
            }
        });

 DiscoveryClientDecorator则是继承了DiscoveryClient,并重写了其中的方法

    @Override
    public List getInstances(String serviceId) {
        // 根据服务 Id, 调用spring cloud的方法获取所有的服务实例
        List instances = getRealInstances(serviceId);
        // 开关是否开启
        Boolean discoveryControlEnabled = PluginContextAware.isDiscoveryControlEnabled(environment);
        if (discoveryControlEnabled) {
            try {
                DiscoveryListenerExecutor discoveryListenerExecutor = applicationContext.getBean(DiscoveryListenerExecutor.class);

                /**
                 *  应该是完成了核心的逻辑,
                 *  instances 直接被传递了出去, 所以这里在内部实现上, 应该是有调用 remove 方法。
                 *
                 *
                 */
                discoveryListenerExecutor.onGetInstances(serviceId, instances);
            } catch (BeansException e) {
                // LOG.warn("Get bean for DiscoveryListenerExecutor failed, ignore to executor listener");
            }
        }

进入到具体的方法内部,就是根据一些规则和配置,从所有服务提供者中,选择出一批符合要求的服务实例(IP,port)

Discovery的大概流程如下:

  1. 注册时,判断了已经注册的实例数。
  2. 获取服务实例的时候,根据规则定义,返回了符合要求的实例。 
  3. 再根据规则定义,对返回的实例数进行了负载。 
  4. 对resttemplate进行了增强,让http的head可以传递下去。

我的注解版:https://github.com/zhaoyb/Discovery

原文地址:https://www.cnblogs.com/beyondbit/p/15305964.html