一、问题背景

在vivo互联网业务高速发展的同时,支撑的服务实例规模也越来越大,然而单个机房能承载的机器容量是有限的,于是同城多机房甚至多地域部署就成为了业务在实际部署过程中不得不面临的场景。

一般情况下,同一个机房内部的网络调用平均时延在0.1ms左右,同城多个机房之间的平均时延在1ms左右,跨地域机房之间的网络时延则更大,例如北京到上海的平均时延达到了30ms以上。

在业务多机房部署场景中,内部服务如果存在大量的跨机房、甚至跨地域的网络调用,则请求时延会显著加大,会直接影响到服务质量,甚至是用户体验。

二、解决方案

要解决以上问题,只需要实现服务消费者和服务提供者之间的网络调用尽量是同机房内部、或者是同地域即可,即服务消费者在调用服务提供者时,优先调用部署在本机房的服务提供者,当本机房没有部署该服务提供者时,再跨机房调用同地域的同城机房、甚至是跨地域机房的服务。

以上策略我们内部称为 就近路由。业务的就近路由示意图如下:

为了简单易用,vivo内部的服务间调用均使用了RPC框架来实现,在Java技术栈方向,我们选择了阿里巴巴开源的RPC框架 Dubbo,针对该场景的问题,我们扩展了Dubbo框架的源码实现,提供了 Dubbo就近路由能力。

三、技术原理说明

在服务提供者注册服务时,把该实例节点的机房信息【我们内部将机房标签定义为 app_loc 字段】注册到注册中心,在开启了就近路由策略后,消费者在过滤服务列表时,会自动筛选、匹配和消费者自己 app_loc 字段相同的服务提供者列表,从而实现就近路由访问。我们实现的就近路由策略,在本机房存在对应服务提供者的情况下,消费者会优先调用本机房的服务。

四、实现方案

开源版本的Dubbo框架并不提供就近路由能力,我们需要基于Dubbo框架源码扩展实现。Dubbo框架整体设计如下:【左侧为服务消费者使用的接口,右侧为服务提供方使用的接口】。

我们知道,Dubbo框架中服务消费者选择具体的服务提供者实例调用的匹配、筛选逻辑是在 Consumer 侧完成的,在 Cluster 层中,消费者会先应用用户配置的 Router 规则,然后再符合规则的服务提供者列表中,使用 LoadBalance 策略选择具体的服务提供者节点进行调用。

结合Dubbo框架源码实现,我们选择基于Dubbo 2.7.x版本的router层扩展接口 org.apache.dubbo.rpc.cluster.Router 实现一种新的路由方式,即就近路由(我们内部标识为 NearestRouter)

有了具体的解决方案,我们很快就完成了代码开发,内部也发布了一个集成就近路由策略的Dubbo版本,但在实际的线上灰度和业务推广过程中,我们实现的初版就近路由碰到了新的问题:

  • 基于机房容量、机器成本等因素考虑,并不是所有的业务都实现了多机房部署,即有部分业务只实现了单机房部署,这部分业务的消费方无法实现同机房内部调用;

  • 即使部分业务实现了多机房部署,但多个机房之间能提供的服务容量并不是相同的,对于服务容量较小的机房,如果一部分服务节点不可用,剩下的服务节点能提供的服务容量无法支撑本机房的消费方调用时,会造成该机房内的服务节点雪崩;

  • 业务侧在开启就近路由策略时,希望消费服务的业务方能逐个开启,有一段时间的灰度观察过程,保证更平滑的升级验证;而不是比较粗暴的要么开启,要么关闭;

  • 部分消费者的Dubbo版本较低,不支持就近路由功能,或者不支持配置应用维度的就近路由,在业务灰度过程中,希望能实现向前兼容,业务侧不报错。

基于以上问题,我们细化了实现方案:

  • 就近路由策略默认不强制执行,即当本机房不存在服务提供者时,不再区分本机房、跨机房,就近路由策略自动失效,优先保障服务之间的正常调用;

  • 支持设置就近路由策略的降级阈值,在调用本机房服务的过程中,当 本机房服务实例数量 / 集群服务实例数量 得到的数值小于设置的降级阈值时,我们认为当前机房的服务容量无法支撑本机房的消费方调用,就近路由策略自动失效;

  • 支持配置应用维度的就近路由策略,即配置的就近路由策略可只针对配置的应用生效,实现应用维度的灰度效果;

  • 实现Dubbo版本自动校验能力,不满足开启就近路由策略条件的业务,提示用户不开启。

有了以上细化方案,我们梳理的就近路由大致逻辑流程如下:

扩展Dubbo框架 Router 接口实现的 NearestRouter 核心代码如下:

public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL consumerUrl, Invocation invocation) throws RpcException {// validate application name (this.url -> routerUrl)String applicationName = getProperty(APP_NAME, consumerUrl.getParameter(CommonConstants.APPLICATION_KEY, ""));boolean validAppFlag = application.equals(applicationName) || CommonConstants.ANY_VALUE.equals(application);if (!validAppFlag) {return invokers;}String local = getProperty(APP_LOC);if (invokers == null || invokers.size() == 0) {return invokers;}List<Invoker<T>> result = new ArrayList<Invoker<T>>();for (Invoker invoker: invokers) {String invokerLoc = getProperty(invoker, invocation, APP_LOC);if (local.equals(invokerLoc)) {result.add(invoker);}}if (result.size() > 0) {if (fallback){// 开启服务降级,available.ratio = 当前机房可用服务节点数量 / 集群可用服务节点数量int curAvailableRatio = (int) Math.floor(result.size() * 100.0d / invokers.size());if (curAvailableRatio <= availableRatio) {return invokers;}}return result;} else if (force) {LOGGER.warn("The route result is empty and force execute. consumerIp: " + NetUtils.getLocalHost()+ ", service: " + consumerUrl.getServiceKey() + ", appLoc: " + local+ ", routerName: " + this.getUrl().getParameterAndDecoded("name"));return result;} else {return invokers;}
}

在vivo内部的服务治理平台上,我们提供了可视化的配置能力,页面内容如下:

通过扩展Dubbo框架,服务治理平台能力支持,我们以上问题都得到了较好的解决。

五、写在将来

虽然以上解决方案能覆盖我们当前业务场景中的大部分问题,随着业务的高速发展,新的业务问题也接踵而至。

  • 当前就近路由策略代码实现集成在Dubbo框架中,业务侧需升级Dubbo框架版本才能完成升级,升级周期长,框架碎片化问题趋向严重;

  • 当前业务服务注册时携带的机房信息比较有限,例如缺失服务实例所在的机架信息,和当前服务同城的其他机房信息等,该类信息可支持我们实现更丰富的就近路由策略;

  • 业务侧的流量灰度策略较丰富,除了就近路由策略之外、往往还需要结合Dubbo框架自带的条件路由、标签路由策略才能实现;

  • 在特定场景下,就近路由策略失效由框架自动完成,业务侧缺少及时的感知能力。

针对以上问题,我们的解决思路如下:

  • 适配云原生ServiceMesh技术方案,实现RPC框架复杂逻辑和业务代码的分层解耦,业务侧集成的SDK功能偏向简单,版本迭代较少,版本碎片化问题能得到较好解决;框架的复杂逻辑下沉到Agent端,框架升级业务基本无感知。幸运的是Dubbo 3.0 版本已规划增加对云原生的支持,我们将持续关注;

  • Dubbo框架的注册中心和内部CMDB系统结合,可以获取到更多维度的信息,不限于该服务节点所在的机架、同城的其他机房信息等。目前vivo内部已启动自研注册中心,可在该场景的能力建设上走的更远;

  • 服务治理平台结合业务侧常用的流量灰度策略,提供结合就近路由、条件路由、标签路由的组合式路由策略,提供更丰富的流量路由能力;

  • 针对框架错误、异常、自适应变更等的告警需求,vivo内部规划建设统一的框架SDK侧的监控告警能力,对于常见的错误、异常、自适应变更等,从SDK侧直接捕获,并和告警中心进行联动,缩短整个监控告警的链路路径,让业务侧能及时感知,甚至是提前感知。

vivo 互联网业务就近路由技术实战相关推荐

  1. 网络流量分析 NetFlow是什么 详解 科普 ~互联网业务流量监测技术的应用和设计---perfect

    前言 随着宽带互联网在中国的迅速发展,全国各大电信运营商的网络规模都在不断扩张,网络结构日渐复杂,网络业务日趋丰富,网络流量高速增长.电信运营商需要通过可靠.有效的网络业务流量监测系统对其网络以及网络 ...

  2. 互联网协议 — 数据路由技术

    目录 文章目录 目录 路由(Routing) 路由表 本地核心路由表 协议路由表 FIB 表 路由记录优先级 路由的度量 等价路由的负载分担,与非等价路由的路由备份 等价路由 负载分担 路由备份 路由 ...

  3. 互联网业务实战(一)--今日头条文章发布实现

    后续会结合互联网具体的业务了解互联网的工作内容.用到的技术栈,主要会讲今日头条的.建议最好先体验下"今日头条"这个APP和头条号这个后台.头条号是给作者发文章用的,跟微信公众号后台 ...

  4. 互联网业务实战(二)--大数据在头条的应用(离线和实时数据处理)

    数据在哪里都是重要的,高考分数.股票价格,在互联网就是dau.用户时长.留存等指标.写代码也要对数据敏感,知道数据的意义是什么,又是怎么算出来的. 这篇聊下头条号的文章发出去之后,被人阅读.评论的那些 ...

  5. 零入门kubernetes网络实战-14->基于veth pair、namespace以及路由技术,实现跨主机命名空间之间的通信测试案例

    <零入门kubernetes网络实战>视频专栏地址 https://www.ixigua.com/7193641905282875942 本篇文章视频地址(稍后上传) 本篇文章继续提供测试 ...

  6. 揭秘卫星互联网!6G关键技术,国内行业雏形初现

    来源:智东西 编辑: 智东西内参 5G的已经全面展开商用,人类的通信技术再一次走上了快速发展期.未来,随着火箭回收.低轨卫星和6G技术的发展,科幻式的通信方式似乎离我们也不远了.2019 年工信部成立 ...

  7. 互联网高并发架构技术实践

    一.什么是高并发 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求. 高并发相关常用的一些指标有响应时间( ...

  8. 手把手教你写网站:Python WEB开发技术实战

    摘要:本文详细介绍了Python WEB开发的基础入门.以一个博客站点的开发为例讲解了基于Django框架开发WEB站点的全过程.通过本文的学习可以快速掌握基于Django的Python WEB的开发 ...

  9. 《网络安全应急响应技术实战指南》知识点总结(第10章 流量劫持网络安全应急响应)

    一.流量劫持概述 1.流量劫持简介 是一种通过在应用系统中植入恶意代码.在网络中部署恶意设备.使用恶意软件等手段,控制客户端与服务端之间的流量通信.篡改流量数据或改变流量走向,造成非预期行为的网络攻击 ...

最新文章

  1. kettle读取不到oracle,kettle链接Oracle数据库,百试不爽!
  2. Noj-589 --糖果
  3. 软件体系结构C2风格
  4. 演练:在 Windows 窗体中承载 Windows Presentation Foundation 复合控件 【转载】
  5. 数据结构 树和二叉树
  6. sql intersect mysql_SQL INTERSECT子句
  7. [vue] 你知道vue2.0兼容IE哪个版本以上吗?
  8. 内聚的极限: 软件开发的不确定性原理
  9. bzoj4567: [Scoi2016]背单词
  10. 【系统架构】ER图的画图规范和优化点
  11. http 请求 返回状态码 405 的问题
  12. 手机开热点但是电脑一直连接不上_电脑无法连接手机开的热点怎么解决
  13. 使用IIS 共享文件
  14. 通信网络与IP网络底层传输技术梳理(SONET/SDH/OTN/ATM/Ethernet/MPLS/PTN...)
  15. 用Power BI (Power query)高效做IPO上市项目账务梳理(财务总监CFO必看)
  16. speedtree树木软件for unity(导出树木/草随风飘动画)
  17. jenkins的应用
  18. mysql 获取当前日期_详解mysql 获取当前日期及格式化
  19. 中职学校计算机教师 述职报告,2011中职学校教师述职报告
  20. JavaScript数据结构之 —— 08哈希表

热门文章

  1. office插件开发_Visual Studio Code有哪些你常用的插件?
  2. java怎样控制迭代周期_如何在Java 8中一年中每周迭代一次?
  3. 教你如何找出 .NET 进程中的所有托管异常
  4. 单片机有什么好的网课?
  5. 服务器上找不到iis,解决IIS服务器部署 字体图标找不到的原因
  6. 线段树 ---- 牛客多校2021多校第6场 H Hopping Rabbit 扫描线
  7. python 序列化函数_python – 如何序列化sympy lambdified函数?
  8. esxi vsphere的端口_vSphere Client 6.0 更改 ESXESXi 主机的端口
  9. python利用requests进行爬虫_Python利用Requests库写爬虫(一)
  10. 【动态规划】状态压缩动态规划