扩展Zuul实现敏捷开发的小小技巧

简介:

分析下目前遇到的痛点

你在开发工作的是否遇到这个问题,微服务模块划分过细,基础模块依赖的比较多?
比如你要进行微服务开发则需要启动以下基础模块

  • 注册中心(eureka)
  • 配置中心(spring cloud config)
  • 网关(zuul)
  • 认证中心(oauth)
  • ...
    如上图红色标注的服务模块,而你需要编码或者需要的只有那么一个业务微服务模块,本地启动这么微服务模块对开发机器的要求性能较高,并且影响开发效率。

为了解决这种问题,团队一般都会把通用的基础模块部,提供统一的开发环境,方便大家开发,如上图 只需要考虑你的业务模块(serviceA、serviceB) 即可,提高开发效率。
这种统一开发基础环境问题存在小小的问题,比如当开发A维护serviceA,开发B维护serviceB 不会出现冲突;如果开发A、B同时维护一个模块时候,就会出现冲突如下图所示:A的本地请求会被路由到B正在开发的biz-service,而不是目标的A的biz-service,因为zuul 是更具服务名称进行路由的

解决原理

重写网关的转发规则,其实就是重写ribbon的路由规则,根据客户端不同的用户请求(可以根据入参不同区分)路由到对应的微服务上,所以对应的微服务上要打上标签。biz-service A开发版本,biz-service B开发版本

代码实现

  1. 在微服务的eureka客户端声明版本所属
eureka:
  instance:
    metadata-map: 
      version: v1.0 # A的开发版本
  1. 自定义ribbon 的断言
/**
 * @author lengleng
 * @date 2018/10/16
 * <p>
 * 路由微服务断言
 * <p>
 * 1. eureka metadata 存在版本定义时候进行判断
 * 2. 不存在 metadata 直接返回true
 */
@Slf4j
public class MetadataCanaryRuleHandler extends ZoneAvoidanceRule {

    @Override
    public AbstractServerPredicate getPredicate() {
        return new AbstractServerPredicate() {
            @Override
            public boolean apply(PredicateKey predicateKey) {
                String targetVersion = RibbonVersionHolder.getContext();
                RibbonVersionHolder.clearContext();
                if (StrUtil.isBlank(targetVersion)) {
                    log.debug("客户端未配置目标版本直接路由");
                    return true;
                }

                DiscoveryEnabledServer server = (DiscoveryEnabledServer) predicateKey.getServer();
                final Map<String, String> metadata = server.getInstanceInfo().getMetadata();
                if (StrUtil.isBlank(metadata.get(SecurityConstants.VERSION))) {
                    log.debug("当前微服务{} 未配置版本直接路由");
                    return true;
                }

                if (metadata.get(SecurityConstants.VERSION).equals(targetVersion)) {
                    return true;
                } else {
                    log.debug("当前微服务{} 版本为{},目标版本{} 匹配失败", server.getInstanceInfo().getAppName()
                            , metadata.get(SecurityConstants.VERSION), targetVersion);
                    return false;
                }
            }
        };
    }
}
  1. 版本上下文TTL
public class RibbonVersionHolder {
    private static final ThreadLocal<String> context = new TransmittableThreadLocal<>();


    public static String getContext() {
        return context.get();
    }

    public static void setContext(String value) {
        context.set(value);
    }

    public static void clearContext() {
        context.remove();
    }
}
  1. 初始化ribbon 路由配置
@Configuration
@ConditionalOnClass(DiscoveryEnabledNIWSServerList.class)
@AutoConfigureBefore(RibbonClientConfiguration.class)
@ConditionalOnProperty(value = "zuul.ribbon.metadata.enabled")
public class RibbonMetaFilterAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public ZoneAvoidanceRule metadataAwareRule() {
        return new MetadataCanaryRuleHandler();
    }
}
  1. 客户端调用时 header 传入版本,以 axios 为例
axios.interceptors.request.use(config => {
  NProgress.start() // start progress bar
  if (store.getters.access_token) {
    config.headers['Authorization'] = 'Bearer ' + token
    config.headers['version'] = 'v1.0'  // 开发人员自己的版本标志,对应eureka metadata 配置
  }
  return config
}

总结

  1. 扩展ribbon 的路由规则,根据客户端来去不同版本的服务,也可以理解为灰度发布。
  2. 生产环境可以借助Kong、Traefik 集合zuul 来实现灰度发布
  3. 代码请参考微服务权限框架pig的灰度发布功能,已经全部开源
  4. 关于pig:
    基于Spring Cloud、oAuth2.0开发基于Vue前后分离的开发平台,支持账号、短信、SSO等多种登录,提供配套视频开发教程。

https://gitee.com/log4j/pig

目录
相关文章
|
测试技术 数据库 安全
带你读《C++代码整洁之道:C++17 可持续软件开发模式实践》之二:构建安全体系
如果想用C++语言编写出易维护的、扩展性良好的以及生命力强的软件,那么,对于所有的软件开发人员、软件设计人员、对现代C++代码感兴趣或想降低开发成本的项目领导者来说,本书都是必需品。如果你想自学编写整洁的C++代码,那么本书也是你需要的。本书旨在通过一些示例帮助各个技术层次的开发人员编写出易懂的、灵活的、可维护的和高效的C++代码。即使你是一名资深的开发工程师,在本书中也可以找到有价值的知识点。
|
7月前
|
敏捷开发 测试技术 项目管理
​ 敏捷开发和传统开发的区别?以及Scrum敏捷管理工具推荐
Leangoo领歌一款永久免费的专业敏捷研发管理工具,它覆盖了敏捷项目研发全流程,包括小型团队敏捷开发,规模化敏捷SAFe,Scrum of Scrums大规模敏捷。能够支持多种场景,如:敏捷研发管理、敏捷项目管理、工作流管理、轻量级项目群管理、任务管理等。
|
8月前
|
敏捷开发 数据可视化 测试技术
敏捷开发要点
敏捷开发是一种以人为核心,迭代、增量式的软件开发方法。它强调团队成员的自我管理、面对变化时的快速适应能力,以及持续的沟通和协作。
|
11月前
|
Java 测试技术 程序员
「敏捷架构」核心实践:测试驱动开发(TDD)简介
「敏捷架构」核心实践:测试驱动开发(TDD)简介
|
11月前
|
存储 编解码 监控
带团队后的日常思考(十二)
带团队后的日常思考(十二)
|
11月前
|
运维 监控 前端开发
带团队后的日常思考(十一)
带团队后的日常思考(十一)
|
12月前
|
敏捷开发 消息中间件 小程序
谈谈软件开发模式:瀑布与敏捷
谈谈软件开发模式:瀑布与敏捷
|
设计模式 机器学习/深度学习 算法
软件测试|测试开发之路--UI 自动化常用设计模式
软件测试|测试开发之路--UI 自动化常用设计模式
167 0
软件测试|测试开发之路--UI 自动化常用设计模式
|
存储 缓存 NoSQL
【老板要我啥都会】|前端升全栈之项目使用express重构项目(下篇)
这个时候我们就可以去把一些自己带有的不用的注释,安装一下我们的mysql和xss.新建一个db文件夹,新建一个mysql.js,将其中的内容拷贝过去,在新建一个conf文件夹,下面建一个db.js,也可以拷贝。
【老板要我啥都会】|前端升全栈之项目使用express重构项目(下篇)
|
JSON 前端开发 JavaScript
【老板要我啥都会】|前端升全栈之项目使用express重构项目(上篇)
实际工作其实是都需要使用框架 / 工具的,可以让我们更加关注业务逻辑(封装了一些基本的 API 什么的),且有一定的流程和标准(中间件机制)来开发插件/ 工具(拆开,低耦合) 什么的来形成一个解决方案.
【老板要我啥都会】|前端升全栈之项目使用express重构项目(上篇)