聊聊服务治理中的路由设计
前言
路由(Route)的设计广泛存在于众多领域,以 RPC 框架 Dubbo 为例,就有标签路由、脚本路由、权重路由、同机房路由等实现。
在框架设计层面,路由层往往位于负载均衡层之前,在进行选址时,路由完成的是 N 选 M(M <= N),而负载均衡完成的是 M 选一,共同影响选址逻辑,最后触发调用。
在业务层面,路由往往是为了实现一定的业务语义,对流量进行调度,所以服务治理框架通常提供的都是基础的路由扩展能力,使用者根据业务场景进行扩展。
今天这篇文章将会围绕路由层该如何设计展开。
路由的抽象建模
先参考 Dubbo 2.7 的实现,进行第一个版本的路由设计,该版本也最直观,非常容易理解。
public interface Router {List<Invoker> route(List<Invoker> invokers, Invocation invocation);
}
Invoker:服务提供方地址的抽象
Invocation:调用的抽象
上述的 route 方法实现的便是 N 选 M 的逻辑。
接下来,以业务上比较常见的同机房路由为例继续建模。顾名思义,在部署时,提供者采用多机房部署,起到容灾的效果,同机房路由最简单的版本即过滤筛选出跟调用方同一机房的地址。
伪代码实现如下:
List<Invoker> route(List<Invoker> invokers, Invocation invocation) {String site = invocation.getSite();List<Invoker> result = new ArrayList<>();for (Invoker invoker: invokers) {if (invoker.getSite().equals(site)) {result.add(invoker);}}return result;
}
Dubbo 在较新的 2.7 版本中,也是采用了这样的实现方式。这种实现的弊端也是非常明显的:**每一次调用,都需要对全量的地址进行一次循环遍历!注意,这是调用级别!**在超大规模的集群下,开销之大,可想而知。
路由的改进方案
基于之前路由的抽象建模,可以直观地理解路由选址的过程,其实也就是 2 步:
根据流量特性与路由规则特性选出对应的路由标。
根据路由标过滤对应的服务端地址列表
纵观整个调用过程:
第一步:一定是动态的,Invocation 可能来自于不同的机房,自然会携带不同的机房标。
第二步:根据路由标过滤对应的服务地址列表,完全是可以优化的,因为服务端的地址列表基本是固定的(在不发生上下线时),可以提前计算好每个机房的地址列表,这样就完成了算法复杂度从 O(N) 到 O(1) 的优化。
基于这个优化思路继续完善,路由选址的过程不应该发生在调用级别,而应该发生在下面两个场景:
地址列表变化时。需要重新计算路由地址列表。
路由规则发生变化时。例如路由规则不再是静态的,可以接受动态配置的推送,此时路由地址列表也需要重新计算。
但无论是哪个场景,相比调用级别的计算量,都是九牛一毛的存在。
优化过后的路由方案,伪代码如下:
Map<String, List<Invoker>> invokerMap = new ArrayList<>();
String originRule;
List<Invoker> originInvokers;void generateRoute(List<Invoker> invokers, String rule) {// 不同路由有不同的路由地址列表计算方式invokerMap = calculate(invokers, rule);
}// 地址推送
void addressNotify(List<Invoker> invokers) {originInvokers = invokers;generateRoute(originInvokers, originRule);
}// 规则变化
void ruleChange(String rule) {originRule = rule;generateRoute(originInvokers, originRule);
}List<Invoker> route(Invocation invocation) {String site = invocation.getSite();return invokerMap.get(site);
}
这份伪代码仅供参考,如果需要实现,仍然需要考虑非常多的细节,例如:
下一级路由如何触发构建
如何确保路由的可观测性
优化过后的方案,路由过程如下:
对比之前,主要是两个变化:
路由的代码组织结构从 pipeline 的链式结构,变成树型结构
建树的过程发生在地址 notify 和规则推送时,在 invocation 级别无需计算
静态路由和动态路由
上述的新方案,并不是特别新奇的概念,正是我们熟知的”打表“。这里也要进行说明,并不是所有的路由场景都可以提前打表,如果某一个路由的实现中,服务地址列表的切分依赖了调用时的信息,自然需要将 N 选 M 的过程延迟到调用时。但根据我个人的经验,大多数的路由实现,基本都是标的匹配过程,无非是路由标的类型,计算标的逻辑不一样而已。
对于这类可以提前打表的路由实现,我们不妨称之为静态路由;而必须在调用级别计算的路由实现,可以称之为动态路由。
上述的优化方案,适用于静态路由场景,并且在真实业务场景中,几乎 90% 的路由实现都是静态路由。
总结
本文以 Dubbo2.7 为例,在其基础上提出了一种静态路由策略的优化方案,可以大大减少路由过程中的计算量。这里也给大家卖个关子,Dubbo 3.0 有没有对这块进行优化呢,采取的是不是本文的静态路由方案呢,背后会不会有其他的思考呢?嘿嘿,本文先不给结论,有知道的小伙伴可以留言告诉大家哦。
- END -
聊聊服务治理中的路由设计相关推荐
- 【微服务架构】在微服务架构中最小化设计时间耦合
理查森:我是克里斯·理查森.欢迎来到我关于在微服务架构中最小化设计时耦合的演讲.在这次演讲中,我将回答三个问题.什么是设计时耦合?这会造成什么问题?我们如何设计松散耦合的服务?这些年来我做了一些事情. ...
- RocketMQ 千锤百炼--哈啰在分布式消息治理和微服务治理中的实践
作者|梁勇 背景 哈啰已进化为包括两轮出行(哈啰单车.哈啰助力车.哈啰电动车.小哈换电).四轮出行(哈啰顺风车.全网叫车.哈啰打车)等的综合化移动出行平台,并向酒店.到店团购等众多本地生活化生 ...
- 哈啰在分布式消息治理和微服务治理中的实践
简介:随着公司业务的不断发展,流量也在不断增长.我们发现生产中的一些重大事故,往往是被突发的流量冲跨的,对流量的治理和防护,保障系统高可用就尤为重要. 作者|梁勇 背景 哈啰已进化为包括两轮出 ...
- 架构专家梁勇:哈啰在分布式消息治理和微服务治理中的实践
背景介绍 哈啰已进化为包括两轮出行(哈啰单车.哈啰助力车.哈啰电动车.小哈换电).四轮出行(哈啰顺风车.全网叫车.哈啰打车)等的综合化移动出行平台,并向酒店.到店团购等众多本地生活化生态探索. 随着公 ...
- 基于Asp.Net Core打造轻量级内部服务治理RPC(二 远程服务设计)
紧接上一篇<基于Asp.Net Core打造轻量级内部服务治理RPC(一)>文章.本文主要讲解基于Asp.Net Core的远程服务设计和实现. 在上一篇中讲过,服务提供者提供的服务实际上 ...
- 微服务体系中的分层设计和领域划分!
上一篇:一个90后员工猝死的全过程 0.2T架构师学习资料干货分享 作者:汤波 来源:https://tbwork.org/2018/10/25/layed-dev-arch/ 本文获得阿里巴巴< ...
- 电商系统中微服务体系中的分层设计和领域划分
说明:在Java生鲜电商平台中,微服务体系的分层设计与领域划分应该怎么样呢? 看标题感觉这个东西很理论,比起"高并发.多线程"."分布式CAP.一致性.Paxos&quo ...
- 浅谈微服务体系中的分层设计和领域划分
1.摘要 本文阐述了一种将分层设计和DDD领域设计应用于微服务体系架构的方案实践,也是个人的最佳实践.对于互联网公司来说,我们主张将其Web服务架构分为五层:基础设施层.领域服务层.应用服务层.网关层 ...
- 基于 Spring Cloud 的服务治理实践
http://www.infoq.com/cn/articles/spring-cloud-based-service-governance 大家好,我是来自贝壳金控的赵文乐,目前主要从事架构方面的工 ...
最新文章
- 剑指Offer_Python实现
- JMS(1)——基本实例
- 多视图几何总结——摄像机模型
- Google API 设计指南 - 前言
- Sublime text无法自动通过package control安装插件的研究
- Capture images using V4L2 on Linux
- C#LeetCode刷题之#172-阶乘后的零(Factorial Trailing Zeroes)
- Ranger开源流水线docker化实践案例
- 视镜:华为云媒体质量管理最新实践
- python处理分组_Python中的groupby分组功能的实例代码
- 旷视科技提出双向网络BiSeNet:实现实时语义分割
- 这几款好加密软件让你不再担心担心隐私泄露!
- WEB应用之JSP+Servlet
- 使用Eclipse编译运行MapReduce程序
- Notification使用举例
- 远程服务器连接计算机和用户名填写,windos系统服务器:添加远程连接用户名方法...
- 快看,这是我为你准备的Python爬取图片教程
- AD域内禁用所有计算机445端口,勒索病毒“永恒之蓝”变种再来,该如何关闭445端口(收藏)(示例代码)...
- 2015年App Store审核被拒的23个理由
- Excel如何隔一行或几行填充颜色
热门文章
- php自动到某个时间提醒,2周后,php脚本cron作业将提醒消息发送到特定的电子邮件地址...
- sql镶嵌查询_sql数据库的嵌套查询
- nginx alias php,Nginx Alias 无法解析PHP的解决办法
- C语言中的关键字详略
- linux ftp显示进度条,在Python中显示FTP下载进度(ProgressBar)
- python实现密码的强度_字符串处理函数(二)python语言实现密码强度校验
- 学习python一开始枯燥_编程零基础应当怎样开始学python?他说,看这三个经典方法...
- 强势 图解 AC自动机(保证您一次就能学会!)
- 1.1 内存的四个分区
- C - Catch That Cow(BFS)