pursue wind pursue wind
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
首页
Java
Python
数据库
框架
Linux
中间件
前端
计算机基础
DevOps
项目
面试
书
关于
归档
MacOS🤣 (opens new window)
GitHub (opens new window)
  • mybatis

  • mybatis-plus

  • Spring

  • SpringBoot

  • SpringSecurity

  • SpringCloud

    • 文档

      • SpringCloud-广告系统实战(七)----广告检索系统(加载全量索引)
      • SpringCloud-广告系统实战(三)---通用模块的开发
      • SpringCloud-广告系统实战(二)---搭建脚手架
      • SpringCloud-广告系统实战(五)---广告检索系统(微服务调用)
      • SpringCloud-广告系统实战(六)----广告检索系统(广告数据索引的设计与实现)
      • SpringCloud-广告系统实战(四)---投放系统的开发
      • SpringCloud-广告系统设计与实现(一)---概述
      • SpringCloud微服务实战(一)-简介
      • SpringCloud微服务实战(七)-异步和消息
      • SpringCloud微服务实战(七)-消息服务在电商中的实践
      • SpringCloud微服务实战(三)-服务注册与发现
      • SpringCloud微服务实战(二)-微服务介绍
      • SpringCloud微服务实战(六)-统一配置中心
      • SpringCloud微服务实战(十)-Hystrix
      • SpringCloud微服务实战(四)-微服务中的服务拆分
    • Gateway

    • Spring Cloud Stream

    • Alibaba Sentinel 规则参数总结
    • Alibaba Sentinel规则持久化-拉模式-手把手教程【基于文件】
    • Feign常见问题总结
    • SentinelResource注解 属性总结
    • Spring Cloud Alibaba Sentienl相关配置项
    • SpringCloudAlibaba
    • SpringCloud入门
    • 使用Spring Cloud Feign上传文件
    • 如何使用Feign构造多参数的请求
    • 实用技巧:Hystrix传播ThreadLocal对象(两种方案)
    • 扩展Ribbon支持Nacos权重的三种方式
    • 扩展Ribbon支持基于元数据的版本管理
      • 元数据
      • 需求分析
      • 写代码
      • 配套代码
    • 搭建生产可用的Nacos集群
  • 单元测试框架Mockito
  • 框架
  • SpringCloud
pursuewind
2020-11-23
目录

扩展Ribbon支持基于元数据的版本管理

# 扩展Ribbon支持基于元数据的版本管理

至此,已经实现了

  • 优先调用同集群下的实例
  • 实现基于权重配置的负载均衡

但实际项目,我们可能还会有这样的需求:

一个微服务在线上可能多版本共存,例如:

  • 服务提供者有两个版本:v1、v2
  • 服务消费者也有两个版本:v1、v2

v1/v2是不兼容的。服务消费者v1只能调用服务提供者v1;消费者v2只能调用提供者v2。如何实现呢?

下面围绕该场景,实现微服务之间的版本控制。

# 元数据

元数据就是一堆的描述信息,以map存储。举个例子:

spring:
  cloud:
    nacos:
        metadata: 
          # 自己这个实例的版本
          version: v1
          # 允许调用的提供者版本
          target-version: v1
1
2
3
4
5
6
7
8

# 需求分析

我们需要实现的有两点:

  • 优先选择同集群下,符合metadata的实例
  • 如果同集群加没有符合metadata的实例,就选择所有集群下,符合metadata的实例

# 写代码

@Slf4j
public class NacosFinalRule extends AbstractLoadBalancerRule {
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Override
    public Server choose(Object key) {
        // 负载均衡规则:优先选择同集群下,符合metadata的实例
        // 如果没有,就选择所有集群下,符合metadata的实例

        // 1. 查询所有实例 A
        // 2. 筛选元数据匹配的实例 B
        // 3. 筛选出同cluster下元数据匹配的实例 C
        // 4. 如果C为空,就用B
        // 5. 随机选择实例
        try {
            String clusterName = this.nacosDiscoveryProperties.getClusterName();
            String targetVersion = this.nacosDiscoveryProperties.getMetadata().get("target-version");

            DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
            String name = loadBalancer.getName();

            NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();

            // 所有实例
            List<Instance> instances = namingService.selectInstances(name, true);

            List<Instance> metadataMatchInstances = instances;
            // 如果配置了版本映射,那么只调用元数据匹配的实例
            if (StringUtils.isNotBlank(targetVersion)) {
                metadataMatchInstances = instances.stream()
                        .filter(instance -> Objects.equals(targetVersion, instance.getMetadata().get("version")))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(metadataMatchInstances)) {
                    log.warn("未找到元数据匹配的目标实例!请检查配置。targetVersion = {}, instance = {}", targetVersion, instances);
                    return null;
                }
            }

            List<Instance> clusterMetadataMatchInstances = metadataMatchInstances;
            // 如果配置了集群名称,需筛选同集群下元数据匹配的实例
            if (StringUtils.isNotBlank(clusterName)) {
                clusterMetadataMatchInstances = metadataMatchInstances.stream()
                        .filter(instance -> Objects.equals(clusterName, instance.getClusterName()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isEmpty(clusterMetadataMatchInstances)) {
                    clusterMetadataMatchInstances = metadataMatchInstances;
                    log.warn("发生跨集群调用。clusterName = {}, targetVersion = {}, clusterMetadataMatchInstances = {}", clusterName, targetVersion, clusterMetadataMatchInstances);
                }
            }

            Instance instance = ExtendBalancer.getHostByRandomWeight2(clusterMetadataMatchInstances);
            return new NacosServer(instance);
        } catch (Exception e) {
            log.warn("发生异常", e);
            return null;
        }
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

负载均衡算法:

public class ExtendBalancer extends Balancer {
    /**
     * 根据权重,随机选择实例
     *
     * @param instances 实例列表
     * @return 选择的实例
     */
    public static Instance getHostByRandomWeight2(List<Instance> instances) {
        return getHostByRandomWeight(instances);
    }
}
1
2
3
4
5
6
7
8
9
10
11

# 配套代码

  • GitHub (opens new window)
  • Gitee (opens new window)
Last Updated: 2023/01/30, 11:01:00
扩展Ribbon支持Nacos权重的三种方式
搭建生产可用的Nacos集群

← 扩展Ribbon支持Nacos权重的三种方式 搭建生产可用的Nacos集群→

Theme by Vdoing | Copyright © 2019-2023 pursue-wind | 粤ICP备2022093130号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜
  • 网络DJ