zoukankan      html  css  js  c++  java
  • SpringCloudAlibaba

    前言

    记录下Ribbon优先调用同一集群下实例的实现


    环境

    Spring Cloud Hoxton.SR9 + Spring Cloud Alibaba 2.2.6.RELEASE + Nacos 1.4.2


    测试用例

    测试内容

    实现内容中心调用用户中心时优先调用同一集群下实例


    用户中心 user-center

    • TestController.java
    @RestController
    @Slf4j
    public class TestController {
    
        @GetMapping("/test/{name}")
        public String test(@PathVariable String name) {
            log.info("请求...");
            return "hello " + name;
        }
    
    }
    

    内容中心 content-center

    • TestController.java
    @GetMapping("test3")
    public String test3() {
        return restTemplate.getForObject(
                "http://user-center/test/{name}",
                String.class,
                "Coisini"
        );
    }
    

    具体实现

    代码配置

    • 服务消费者(内容中心)配置如下:
    • NacosSameClusterWeightedRule.java
    import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
    import com.alibaba.cloud.nacos.ribbon.ExtendBalancer;
    import com.alibaba.cloud.nacos.ribbon.NacosServer;
    import com.alibaba.nacos.api.exception.NacosException;
    import com.alibaba.nacos.api.naming.NamingService;
    import com.alibaba.nacos.api.naming.pojo.Instance;
    import com.netflix.client.config.IClientConfig;
    import com.netflix.loadbalancer.AbstractLoadBalancerRule;
    import com.netflix.loadbalancer.BaseLoadBalancer;
    import com.netflix.loadbalancer.Server;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.util.CollectionUtils;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    import java.util.stream.Collectors;
    
    /**
     * @Description Ribbon-同一集群优先调用
     */
    @Slf4j
    public class NacosSameClusterWeightedRule extends AbstractLoadBalancerRule {
    
        @Autowired
        private NacosDiscoveryProperties nacosDiscoveryProperties;
    
        /**
         * 读取配置文件,并初始化 NacosWeightedRule
         * @param iClientConfig
         */
        @Override
        public void initWithNiwsConfig(IClientConfig iClientConfig) {
    
        }
    
        /**
         * 同一集群优先调用
         * @param o
         * @return
         */
        @Override
        public Server choose(Object o) {
    
            try {
                // 拿到配置文件中的集群名称 kunming
                String clusterName = nacosDiscoveryProperties.getClusterName();
    
                BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
                // 想要请求的微服务的名称
                String name = loadBalancer.getName();
    
                // 拿到服务发现的相关API
                NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
    
                // 1. 找到指定服务的所有实例 A
                List<Instance> instances = namingService.selectInstances(name, true);
    
                // 2. 过滤出相同集群下的所有实例 B
                List<Instance> sameClusterInstances = instances.stream()
                        .filter(instance -> Objects.equals(instance.getClusterName(), clusterName))
                        .collect(Collectors.toList());
    
                // 3. 如果B是空,就用A
                List<Instance> instancesToBeChosen = new ArrayList<>();
                if (CollectionUtils.isEmpty(sameClusterInstances)) {
                    instancesToBeChosen = instances;
                    log.warn("发生跨集群的调用, name = {}, clusterName = {}, instances = {}",
                            name,
                            clusterName,
                            instances
                    );
                } else {
                    instancesToBeChosen = sameClusterInstances;
                }
    
                // 4. 基于权重的负载均衡算法,返回1个实例
                Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToBeChosen);
                log.info("选择的实例是 port = {}, instance = {}", instance.getPort(), instance);
    
                return new NacosServer(instance);
            } catch (NacosException e) {
                log.error("Nacos同一集群优先调用异常", e);
                return null;
            }
        }
    }
    
    • RibbonConfiguration.java
    import com.coisini.contentcenter.configuration.NacosSameClusterWeightedRule;
    import com.netflix.loadbalancer.IRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @Description Ribbon配置类
     */
    @Configuration
    public class RibbonConfiguration {
        /**
         * 自定义负载均衡规则
         * NacosSameClusterWeightedRule 同集群优先调用
         * @return
         */
        @Bean
        public IRule ribbonRule() {
            return new NacosSameClusterWeightedRule();
        }
    }
    
    • UserCenterRibbonConfiguration.java
    import org.springframework.cloud.netflix.ribbon.RibbonClients;
    import org.springframework.context.annotation.Configuration;
    import ribbonconfiguration.RibbonConfiguration;
    
    /**
     * @Description 用户中心配置类
     */
    @Configuration
    @RibbonClients(defaultConfiguration = RibbonConfiguration.class)
    public class UserCenterRibbonConfiguration {
    }
    
    • content-center -> application.yml,内容中心配置集群为kunming
    spring:
      application:
        # 服务名称
        name: content-center
      cloud:
        nacos:
          discovery:
            # 指定nacos server的地址
            server-addr: localhost:8848
            # 集群名称 kunming 
            cluster-name: kunming 
    

    测试

    • user-center -> application.yml,启动用户中心双实例,集群-端口分别为yuxi-8081kunming-8082
    # 8081 端口 实例1
    spring:
      application:
        # 服务名称
        name: user-center
      cloud:
        nacos:
          discovery:
            # 指定nacos server的地址
            server-addr: localhost:8848
            # 指定集群名称
            cluster-name: yuxi
    
    # 8082 端口 实例2
    spring:
      application:
        # 服务名称
        name: user-center
      cloud:
        nacos:
          discovery:
            # 指定nacos server的地址
            server-addr: localhost:8848
            # 指定集群名称
            cluster-name: kunming
    
    • 启动效果如下所示,因内容中心与用户中心(8082)属于同一集群kunming,发生调用时会优先选择8082端口的用户中心

    在这里插入图片描述


    在这里插入图片描述

    • 访问测试接口http://localhost:8010/test3

    在这里插入图片描述

    • 关闭用户中心(8082)实例再次访问

    在这里插入图片描述
    ...至此,已实现Ribbon的同集群优先调用


    项目源码


    - End -
    白嫖有风险
    点赞加收藏
    以上为本篇文章的主要内容,希望大家多提意见,如果喜欢记得点个推荐哦
    作者:Maggieq8324
    本文版权归作者和博客园共有,欢迎转载,转载时保留原作者和文章地址即可。
  • 相关阅读:
    django 项目运行时static静态文件不能加载问题处理
    django 项目运行时media静态文件不能加载问题处理
    django 的用户验证及登录状态保持
    django 2.0 中URL的include方法使用分析
    auth.User.groups: (fields.E304)
    web理论知识--HTML结构及标签
    数据库相关--mysql中的单表查询
    python基础下的数据结构与算法之链表
    python基础下的数据结构与算法之顺序表
    Nginx 日志分析命令
  • 原文地址:https://www.cnblogs.com/maggieq8324/p/15323484.html
Copyright © 2011-2022 走看看