Spring Cloud开发人员如何解决服务冲突和实例乱窜?

标签: | 发表时间:2019-09-06 15:04 | 作者:
出处:https://mp.weixin.qq.com

一、背景

在我们开发微服务架构系统时,虽然说每个微服务都是孤立的可以单独开发,但实际上并非如此,要调试和测试你的服务不仅需要您的微服务运行,还需要它的上下文服务、依赖的基础服务等都要运行;但如果你的系统服务数和依赖比较多呢,那就是一个比较棘手的问题!有没有办法能提高开发效率呢?

如上图所示,我们能不能用服务器把所有的服务都部署起来,然后开发只在本地运行自己所负责开发的服务,因为需要依赖其他服务所以本地启动的服务也需要注册到公共的注册中心里;

例子中 业务服务B有3台实例注册到注册中心里

分别是:服务上的、开发A与开发B自己本机启动的

但是这样做又会出现新的问题:服务会冲突乱窜,意思就是 开发A在debug自己的 业务服务B服务的时候可能请求会跳转到其他人的实例上(服务器、开发B)

 

二、解决思路

解决这个服务乱窜问题有一个比较优雅的方式就是 自定义负载均衡规则,主要实现以下目标:

  1. 普通用户访问服务器上的页面时,请求的所有路由只调用 服务器上的实例

  2. 开发A访问时,请求的所有路由优先调用 开发A本机启动的实例,如果没有则调用 服务器上的实例

  3. 开发B访问时同上,请求的所有路由优先调用 开发B本机启动的实例,如果没有则调用 服务器上的实例

 

三、具体实现

要实现上面的目标有两个比较关键的问题需要解决

  1. 区分 不同用户的服务实例

  2. 实现 自定义负载均衡规则

3.1. 区分不同用户的服务实例

直接使用注册中心的元数据(metadata)来区分就可以了

主流的注册中心都带有元数据管理

Nacos为例,只需要在配置文件下添加

  spring:   
cloud:
nacos:
discovery:
server-addr: localhost:8848
metadata:
version: zlt

metadata下的 version就是我添加的元数据 key为version, value为zlt


启动服务后元数据就会注册上去,如下图

经过元数据区分后,目前是下面这个情况,服务器的实例 version为空,而开发人员自己本地启动的实例 version为唯一标识(自己的名字)

 

3.2. 自定义负载均衡规则

首先在 Spring Cloud微服务框架里实例的负载均衡是由 Ribbon负责。
CustomIsolationRule类

  public class CustomIsolationRule extends RoundRobinRule {   
/**
* 优先根据版本号取实例
*/
@Override
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
String version = LbIsolationContextHolder.getVersion();
List<Server> targetList = null;
List<Server> upList = lb.getReachableServers();
if (StrUtil.isNotEmpty(version)) {
//取指定版本号的实例
targetList = upList.stream().filter(
server -> version.equals(
((NacosServer) server).getMetadata().get(CommonConstant.METADATA_VERSION)
)
).collect(Collectors.toList());
}

if (CollUtil.isEmpty(targetList)) {
//只取无版本号的实例
targetList = upList.stream().filter(
server -> {
String metadataVersion = ((NacosServer) server).getMetadata().get(CommonConstant.METADATA_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);
}
}

集成轮询规则 RoundRobinRule来实现,主要的逻辑为

  1. 根据上游输入的版本号 version,有值的话则取 服务元信息version值一样的实例

  2. 上游的版本号 version没值或者该版本号匹配不到任何服务,则只取 服务元信息version值为空的实


并通过配置开关控制是否开启自定义负载规则

  @Configuration   
@ConditionalOnProperty(value = "zlt.ribbon.isolation.enabled", havingValue = "true")
@RibbonClients(defaultConfiguration = {RuleConfigure.class})
public class LbIsolationConfig {

}

 

相关源码

https://gitee.com/zlt2000/microservices-platform/blob/master/zlt-commons/zlt-ribbon-spring-boot-starter/src/main/java/com/central/common/ribbon/rule/CustomIsolationRule.java


四、总结

上面提到的区分服务实例和自定义负载规则为整个解决思路的核心点,剩下要做的就是上游的 version怎样指定呢?,下面我提供两个思路

  • 开发人员自己启动前端工程,通过配置参数,统一在前端工程传递 version

  • 通过 postman调用接口的时候在header参数中添加



参考
https://github.com/Nepxion/Discovery


相关 [spring cloud 开发] 推荐:

大话 Spring Cloud

- - IT瘾-dev
研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud. 在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统构建的要求,使我们以非常低的成本(技术或者硬件)搭建一套高效、分布式、容错的平台,但Spring Cloud也不是没有缺点,小型独立的项目不适合使用.

Spring Cloud限流详解 | Spring Cloud|周立

- -
限流往往是一个绕不开的话题. 本文详细探讨在Spring Cloud中如何实现限流. Zuul上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. 常见的限流算法有漏桶算法以及令牌桶算法. https://www.cnblogs.com/LBSer/p/4083131.html,写得通俗易懂,你值得拥有,我就不拽文了.

Spring Cloud Kubernetes指南

- -
当我们构建微服务解决方案时,SpringCloud和Kubernetes都是最佳解决方案,因为它们为解决最常见的挑战提供组件. 但是,如果我们决定选择Kubernetes作为我们的解决方案的主要容器管理器和部署平台,我们仍然可以主要通过SpringCloudKubernetes项目使用SpringCloud的有趣特性.

Spring Cloud 快速入门

- - IT瘾-tuicool
Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它将市面上较好的微服务框架集成进来,从而简化了开发者的代码量. 本课程由浅入深带领大家一步步攻克 Spring Cloud 各大模块,接着通过一个实例带领大家了解大型分布式微服务架构的搭建过程,最后深入源码加深对它的了解.

Deploy the spring cloud project using jenkins

- - Telami
先简单记录下Jenkins部署maven聚合工程要点. Root pom配置成项目根目录的pom.xml. maven命令单独install 欲构建的项目. 选项后可跟随{groupId}:{artifactId}或者所选模块的相对路径(多个模块以逗号分隔). 表示同时处理选定模块所依赖的模块. 表示同时处理依赖选定模块的模块.

Spring Cloud Gateway(限流) | Wind Mt

- -
限流可以保障我们的 API 服务对所有用户的可用性,也可以防止网络攻击. 一般开发高并发系统常见的限流有:限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如 nginx 的 limit_conn 模块,用来限制瞬时并发连接数)、限制时间窗口内的平均速率(如 Guava 的 RateLimiter、nginx 的 limit_req 模块,限制每秒的平均速率);其他还有如限制远程接口调用速率、限制 MQ 的消费速率.

快速突击 Spring Cloud Gateway

- - 掘金后端
认识 Spring Cloud Gateway. Spring Cloud Gateway 是一款基于 Spring 5,Project Reactor 以及 Spring Boot 2 构建的 API 网关,是 Spring Cloud 微服务生态的主要组件之一. Spring Cloud Gateway 主要负责接口请求的路由分发,并且支持对请求的安全验证,流量监控和流量控制等扩展操作.

Spring Cloud Gateway2.0实践报告

- - 掘金后端
你的点赞就是对我最大的支持. 原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处. 本文将从知识拓扑讲起,谈一下api网关的功能,以及spring cloud gateway的使用方法. 一、知识拓扑 (使用和原理) 二、网关的作用 三、Predicate,路由匹配 四、Filter,过滤器编写 五、自定义过滤器 六、常见问题 复制代码.

Spring Cloud开发人员如何解决服务冲突和实例乱窜?

- -
在我们开发微服务架构系统时,虽然说每个微服务都是孤立的可以单独开发,但实际上并非如此,要调试和测试你的服务不仅需要您的微服务运行,还需要它的上下文服务、依赖的基础服务等都要运行;但如果你的系统服务数和依赖比较多呢,那就是一个比较棘手的问题. 如上图所示,我们能不能用服务器把所有的服务都部署起来,然后开发只在本地运行自己所负责开发的服务,因为需要依赖其他服务所以本地启动的服务也需要注册到公共的注册中心里;.

微服务框架Spring Cloud介绍 Part2: Spring Cloud与微服务

- - skaka的博客
之前介绍过 微服务的概念与Finagle框架, 这个系列介绍Spring Cloud.. Spring Cloud还是一个相对较新的框架, 今年(2016)才推出1.0的release版本. 虽然Spring Cloud时间最短, 但是相比我之前用过的Dubbo和Finagle, Spring Cloud提供的功能最齐全..