从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题

简介: 从0到1 手把手搭建spring cloud alibaba 微服务大型应用框架(六)开发篇-如何解决微服务开发环境请求实例转发到别人机器问题

image.png当前公司内微服务开发一般有两种模式


1.开发启动所有服务,注册中心,网关,认证服务等都在自己机器启动


优点:可以保证自己发送的请求(经过网关的请求或者通过fegin调用的请求)都能达到自己机器的服务


缺点:如果服务过多,电脑有可能会承受不住


2.开发只启动自己需要开发的服务,注册中心,网关,认证服务等都在一个公用的服务器启动,所有人启动的服务都注册到了这个公用服务上


优点:只需要启动自己开发的服务,方便快捷,节省电脑资源

缺点:由于自己开发的服务不一定只有自己启动了,有可能有别人同时启动了该服务,所以当从前端请求或者通过fegin请求时,可能请求会发送到了别人机器启动的服务上


模式2会有请求发送到别人机器对应服务的情况,具体情况明细图如下


1.png

图1

说明:

图1 通过网关请求后台服务A ,由于两个开发人员都启动了服务A并且注册到了公用注册中心上,使用默认负载均衡策略得话,此时请求到的不一定是小李的还是小张的电脑的服务A

1.png

图2


说明:

图二 通过fegin请求后台服务A ,由于两个开发人员都启动了服务A并且注册到了公用注册中心上,使用默认负载均衡策略得话,所以此时请求到的不一定是小李的还是小张的电脑的服务A

解决方案,由于上面问题都是在负载均衡获取实例时随机去到了一个实例,所以解决方式就是重写负载均衡路由指定获取特定的实例

网关端重写路由解决方案解决图1问题

1.png

代码,添加如下这几个类

1.png

CustomRibbonRule.java

public class CustomRibbonRule extends RoundRobinRule {
    private String version;
    public void setVersion(String version) {
        this.version = version;
    }
    @Override
    public Server choose(ILoadBalancer lb, Object key) {
        List<Server> targetList = null;
        List<Server> upList = lb.getReachableServers();
        if (StrUtil.isEmpty(version)) {
            version = ReqeustHeaderContextHolder.getVersion();
        }
        if (StrUtil.isNotEmpty(version)) {
            //取指定版本号的实例
            targetList = upList.stream().filter(
                    server -> version.equals(
                            ((NacosServer) server).getMetadata().get("version")
                    )
            ).collect(Collectors.toList());
        }
        if (CollUtil.isEmpty(targetList)) {
            //只取无版本号的实例
            targetList = upList.stream().filter(
                    server -> {
                        String metadataVersion = ((NacosServer) server).getMetadata().get("version");
                        return StrUtil.isEmpty(metadataVersion);
                    }
            ).collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(targetList)) {
            return getServer(targetList);
        }
        return super.choose(lb, key);
    }
    private Server getServer(List<Server> upList) {
        int nextInt = RandomUtil.randomInt(upList.size());
        return upList.get(nextInt);
    }
}

RibbonConfiguration.java

@Configuration
public class RibbonConfiguration {
    @Value("${spring.cloud.nacos.discovery.metadata.version:#{null}}")
    private String version;
    @Bean
    public IRule defaultLBStrategy() {
        CustomRibbonRule customIsolationRule = new CustomRibbonRule();
        customIsolationRule.setVersion(version);
        return customIsolationRule;
    }
}

ReqeustHeaderContextHolder.java

public class ReqeustHeaderContextHolder {
    private static final FastThreadLocal fastThreadLocal = new FastThreadLocal();
    public static void putVersion(String version){
        fastThreadLocal.set(version);
    }
    public static String getVersion(){
        return Objects.isNull(fastThreadLocal.get())?null:(String) fastThreadLocal.get();
    }
    public static void clear(){
        fastThreadLocal.remove();
    }
}

OrderedGatewayFilter.java

public class OrderedGatewayFilter implements GatewayFilter, Ordered {
    private final GatewayFilter delegate;
    private final int order;
    public OrderedGatewayFilter(GatewayFilter delegate, int order) {
        this.delegate = delegate;
        this.order = order;
    }
    public GatewayFilter getDelegate() {
        return delegate;
    }
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try{
            if(CollectionUtil.isNotEmpty(exchange.getRequest().getHeaders().get("version"))){
                String version = exchange.getRequest().getHeaders().get("version").get(0);
                ReqeustHeaderContextHolder.putVersion(version);
            }
            return this.delegate.filter(exchange, chain);
        }finally {
            ReqeustHeaderContextHolder.clear();
        }
    }
    @Override
    public int getOrder() {
        return this.order;
    }
    @Override
    public String toString() {
        return new StringBuilder("[").append(delegate).append(", order = ").append(order)
                .append("]").toString();
    }
}

fegin端重写路由解决方案解决图2问题

1.png

服务fegin的负载均衡路由,注册时将自己机器的服务A加上特定key属性注册到注册中心内,获取时优先获取有指定key的实例,没有找到再随机获取一个实例


代码:

各个应用部分可以添加如下类或者抽取出共通类

1.png

CustomRibbonRule.java

public class CustomRibbonRule extends RoundRobinRule {
    private String version;
    public void setVersion(String version) {
        this.version = version;
    }
    @Override
    public Server choose(ILoadBalancer lb, Object key) {
        List<Server> targetList = null;
        List<Server> upList = lb.getReachableServers();
        if (StrUtil.isNotEmpty(version)) {
            //取指定版本号的实例
            targetList = upList.stream().filter(
                    server -> version.equals(
                            ((NacosServer) server).getMetadata().get("version")
                    )
            ).collect(Collectors.toList());
        }
        if (CollUtil.isEmpty(targetList)) {
            //只取无版本号的实例
            targetList = upList.stream().filter(
                    server -> {
                        String metadataVersion = ((NacosServer) server).getMetadata().get("version");
                        return StrUtil.isEmpty(metadataVersion);
                    }
            ).collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(targetList)) {
            return getServer(targetList);
        }
        return super.choose(lb, key);
    }
    private Server getServer(List<Server> upList) {
        int nextInt = RandomUtil.randomInt(upList.size());
        return upList.get(nextInt);
    }
}

RibbonConfiguration.java

@Configuration
public class RibbonConfiguration {
    @Value("${spring.cloud.nacos.discovery.metadata.version:#{null}}")
    private String version;
    @Bean
    public IRule defaultLBStrategy() {
        CustomRibbonRule customIsolationRule = new CustomRibbonRule();
        customIsolationRule.setVersion(version);
        return customIsolationRule;
    }
}

然后对应yml里面添加自己对应的version

1.png

大功告成,看看效果


首先在需要走自己机器的服务上加上对应version,都启动后如下图

1.png

1.png

我们通过postman 模拟前端请求网关访问看看是不是走的我们指定的xiaoli 的实例

1.png

可以看到我们网关自定义的负载路由去到了version=xiaoli的实例


再来看看fegin调用的时候是不是也是走的我们指定version的实例

1.png

可以看order调用商品服务的时候也是找了商品服务version为xiaoli的实例,整明两个问题都解决了

相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
7月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
5091 97
|
7月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
7709 106
|
8月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
649 2
|
7月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
7月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
658 8
|
7月前
|
人工智能 监控 Java
Spring AI Alibaba实践|后台定时Agent
基于Spring AI Alibaba框架,可构建自主运行的AI Agent,突破传统Chat模式限制,支持定时任务、事件响应与人工协同,实现数据采集、分析到决策的自动化闭环,提升企业智能化效率。
Spring AI Alibaba实践|后台定时Agent
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
876 6
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
458 1
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1

热门文章

最新文章