SOFAMesh解决方案x-protocol介绍系列(1) : DNS通用寻址方案

简介:

小蚂蚁说:

2018年上半年,蚂蚁金服决定基于 Istio 订制自己的 ServiceMesh 解决方案,并在6月底正式对外公布了 SOFAMesh,详情可直接点击之前的文章查看: 大规模微服务架构下的Service Mesh探索之路 。

在 SOFAMesh 的开发过程中,针对遇到的实际问题,我们给出了一套名为 x-protocol 的解决方案,本文将会对这个解决方案进行详细的讲解,后面会有更多内容,欢迎持续关注本系列文章。

前言

x-protocol 的定位是云原生、高性能、低侵入性的通用 Service Mesh 落地方案,依托 Kubernetes 基座,利用其原生的服务注册和服务发现机制,支持各种私有 RPC 协议低成本、易扩展的接入,快速享受 Service Mesh 所带来的红利。

具体解决的问题包括:

  • 多通讯协议支持问题,减少开发工作量,简单快捷的接入新协议
  • 尽量提升性能,提供更灵活的性能与功能的平衡点选择,满足特定高性能场景
  • 兼容现有SOA体系,提供通过接口进行访问的方式,实现不修改业务代码也能顺利接入 Service Mesh
  • 支持单进程多服务的传统SOA程序,可以在微服务改造之前,先受益于 Service Mesh 带来的强大功能


在本系列文章中,我们将对此进行详细的讲解,首先是“DNS通用寻址方案”。

背景和需求

SOA的服务模型

在SOFAMesh计划支持的RPC框架中,SOFARPC、HSF、Dubbo都是一脉相承的SOA体系,也都支持经典的SOA服务模型,通常称为”单进程多服务”,或者叫做”单进程多接口”。(备注:由于服务一词使用过于频繁,下文都统一称为接口以便区分)

SOA标准的服务注册,服务发现和调用流程如下:



  1. 在单个SOA应用进程内,存在多个接口
  2. 服务注册时,以接口为单位进行多次独立的服务注册
  3. 当客户端进行调用时,按照接口进行服务发现,然后发起调用


当我们试图将这些SOA架构的应用搬迁到ServiceMesh时,就会遇到服务模型的问题:微服务是单服务模型,也就是一个进程里面只承载一个服务。以k8s的服务注册为例,在单进程单服务的模型下,服务名和应用名可以视为一体,k8s的自动服务注册会将应用名作为服务注册的标示。

这就直接导致了SOA模型和微服务模型的不匹配问题:

  • SOA以接口为单位做服务注册和服务发现,而微服务下是服务名
  • SOA是”单进程多接口”,而微服务是”单进程单服务”


一步接一步的需求

  • 先上车后补票
  • 最理想的做法当然是先进行微服务改造,实现微服务拆分。但是考虑到现有应用数量众多,我们可能更愿意在大规模微服务改造之前,先想办法让这些应用可以运行在ServiceMesh下,提前受益于ServiceMesh带来的强大功能。因此,我们需要找到一个合适的方案,让ServiceMesh支持没有做微服务改造依然是”单进程多接口”形式的传统SOA应用,所谓”先上车后补票”。
  • 不修改代码
  • 考虑到原有的SOA应用,相互之间错综复杂的调用关系,最好不要修改代码,即保持客户端依然通过接口名来访问的方式。当然,SOA架构的客户端SDK可能要进行改动,将原有的通过接口名进行服务发现再自行负载均衡进行远程调用的方式,精简为标准的ServiceMesh调用(即走Sidecar),因此修改SDK依赖包和重新打包应用是不可避免。
  • 支持带特殊字符的接口名
  • k8s的服务注册,Service名是不能携带”.“号的。而SOA架构下,接口名有时出于管理方便,有可能是加了域名前缀,如”com.alipay.demo.interface-2”。为了实现不修改原有代码,就只能想办法支持这种带特殊字符的接口名。


参考Kubernetes和Istio

在进一步讨论解决方案之前,我们先来看一下kubernetes和istio中的标准请求寻址方式。

(备注:过程稍显复杂,涉及到k8s/istio的一些底层细节。但是了解这个过程对后续的理解非常重要,也可以帮助大家了解k8s和k8s的工作原理,强烈推荐阅读。)

k8s下的DNS寻址方式

在k8s下,如图所示,假定我们部署了一个名为userservice的应用,有三个实例,分别在三个pod中。则应用部署之后,k8s会为这个应用分配ClusterIP和域名,并在DNS中生成一条DNS记录,将域名映射到ClusterIP:

当部署在k8s下的某个充当客户端的应用发起请求时,如图中的HTTP GET请求,目标URL地址为 “http://userservice/id/1000221"。请求的寻址方式和过程如下:

  • 首先进行域名解析,分别尝试解析”userservice”/“userservie.default.svc.cluster.local”等域名,得到ClusterIP
  • 然后客户端发出请求的报文,目标地址为ClusterIP,源地址为当前客户端所在的pod IP(简单起见,端口先忽略)
  • 请求报文随即被kube-proxy拦截,kube-proxy根据ClusterIP,拿到ClusterIP对应的多个实际服务实例所在的pod ip,取其中一个,修改目标地址为这个pod IP
  • 请求报文最终就被发送到服务实例所在的pod IP


应答回来的方式类似,userservice发出的应答报文会被kube-proxy拦截并修改为发送到客户端所在的pod IP。

我们详细看一下请求和应答全称的四个请求包的具体内容(简单起见继续忽略端口):


重点关注请求和应答报文的源地址和目标地址:

  • 客户端发出的请求,为”客户端到ClusterIP”
  • kube-proxy拦截到请求后,将请求修改为”客户端到服务器端”
  • 服务器端收到请求时,表现为”客户端到服务器端”,ClusterIP被kube-proxy屏蔽
  • 服务器端发送应答,因为收到的请求看似来自客户端,因此应答报文为”服务器端到客户端”
  • 应答报文被kube-proxy拦截,将应答修改为”ClusterIP到服务器端”
  • 客户端收到应答,表现为”ClusterIP到服务器端”,服务器端IP被kube-proxy屏蔽


kube-proxy在客户端和服务器端之间拦截并修改请求和应答的报文,联通两者,但各自屏蔽了一些信息:

  • 在客户端看来它是在和ClusterIP交互,userservice的具体服务器端实例对客户端是无感知的
  • 在服务器端看来,客户端是直接在和它交互,ClusterIP的存在对服务器端是无感知的


更深入一步,看kube-proxy在两个拦截和修改报文中的逻辑处理关系,即kube-proxy是如何在收到应答时正确的找回原有的ClusterIP:

  1. 在拦截并修改请求报文之后,kube-proxy会保存报文修改的5元组对应关系(5元组指源IP地址,源端口,协议,目的地IP地址,目的地端口)
  2. 在收到应答报文后,根据应答报文中的5元组,在保存的5元组对应关系中,找到对应信息,得到原有的ClusterIP和端口,然后修改应答报文


总结,通过上述k8s下的寻址方式,客户端只需发送带简单寻址信息的请求(如 “http://userservice/id/1000221" 中的”userservice” ),就可以寻址到正确的服务器端。这期间有两个关注点:

  1. 通过DNS,建立了域名和ClusterIP的关系。
  2. 对于客户端,这是它能看到的内容,非常的简单,域名、DNS是非常容易使用的。
  3. 而通过kube-proxy的拦截和转发,又打通了ClusterIP和服务器端实际的Pod IP
  4. 对于客户端,这些是看不到的内容,不管有多复杂,都是k8s在底层完成,对客户端,或者说使用者透明。


以客户端的视角看来,这个DNS寻址方式非常的简单直白:

Istio的DNS寻址方式

Istio的请求寻址方式和普通kubernetes非常相似,原理相同,只是kube-proxy被sidecar取代,然后sidecar的部署方式是在pod内部署,而且客户端和服务器端各有一个sidecar。其他基本一致,除了图中红色文本的部分:

  • iptables在劫持流量时,除了将请求转发到localhost的Sidecar处外,还额外的在请求报文的TCP options 中将 ClusterIP 保存为 original dest。
  • 在 Sidecar (Istio默认是Envoy)中,从请求报文 TCP options 的 original dest 处获取 ClusterIP


通过TCP options 的 original dest,iptables就实现了在劫持流量到Sidecar的过程中,额外传递了 ClusterIP 这个重要参数。Istio为什么要如此费力的传递这个 ClusterIP 呢?

看下图就知道了,这是一个 Virtual Host 的示例, Istio 通过 Pilot 将这个规则发送给 Sidecar/Envoy ,依靠这个信息来匹配路由请求找到处理请求的cluster:


domains中,除了列出域名外,还有一个特殊的IP地址,这个就是k8s服务的 ClusterIP!因此,Sidecar可以通过前面传递过来的 ClusterIP 在这里进行路由匹配(当然也可以从报文中获取destination然后通过域名匹配)。

总结,Istio延续了k8s的寻址方式,客户端同样只需发送带简单寻址信息的请求,就可以寻址到正确的服务器端。这期间同样有两个关注点:

  1. 通过DNS,建立了域名和ClusterIP的关系。
  2. 通过 ClusterIP 和 Pilot 下发给 Virtual Host 的配置,Sidecar 可以完成路由匹配,将ClusterIP和目标服务器关联起来
  3. 同样,对于客户端,这些是看不到的内容。


因此,以客户端的视角看来,Isito的这个DNS寻址方式同样的简单直白!

DNS通用寻址方案具体介绍

解决问题的思路

在详细讲述了k8s和istio的DNS寻址方案之后,我们继续回到我们的主题,我们要解决的问题:

如何在不修改代码,继续使用接口的情况下,实现在Service Mesh上运行现有的Dubbo/HSF/SOFA等传统SOA应用?

这里有一个关键点:k8s的服务注册是以基于Service或者说基于应用(app name),而我们的客户端代码是基于接口的。因此,在 Virtual Host 进行路由匹配时,是不能通过域名匹配的。当然,这里理论上还有一个思路,就是将接口注册为k8s Service。但是,还记得要支持接口特殊字符的需求吗?带点号的接口名,k8s是不能接受它作为Service Name的,直接堵死了将接口名注册到k8s Service的道路。

这样,我们就只有一条路可以走了:效仿istio的做法,通过 ClusterIP 匹配!

而要将接口名(如”com.alipay.demo.interface-1”)和 ClusterIP 关联,最简单直接的方式就是打通DNS :

只需要在DNS记录中,增加接口到 ClusterIP 的映射,然后就可以完全延续Istio的标准做法!其他的步骤,如域名解析到ClusterIP,iptables拦截并传递ClusterIP,sidecar读取ClusterIP并匹配路由,都完全可以重用原有方案。

具体实现方案

实现时,我们选择了使用 CoreDNS 作为k8s的DNS解决方案,然后通过 Service Controller 操作 CoreDNS 的记录来实现DNS解析。

为了收集到SOA应用的接口信息,我们还提供了一个 Register Agent 给 Service Controller 收集信息。

详细的实现方案,不在本文中重复讲述,请参阅我们之前的分享文章 SOFAMesh 的通用协议扩展 中的DNS寻址方案一节。

(备注:暂时修改 CoreDNS 记录的方式是直接修改 CoreDNS 的底层数据,不够优雅。未来将修改为通过 CoreDNS 的 Dynamic updates API 接口进行,不过 CoreDNS 的这个API还在开发中,需要等待完成。)

单进程多接口问题的解决

上面的解决方案,在解决通过接口实现访问的同时,也将”单进程多接口”的问题一起解决了:

  • 原SOA应用上k8s时,可以注册为标准的k8s Service,获取ClusterIP。此时使用应用名注册,和接口无关。
  • 通过操作 CoreDNS,我们将该SOA应用的各个接口都添加为 DNS 记录,指向该应用的ClusterIP
  • 当客户端代码使用不同的接口名访问时,DNS解析出来的都是同一个ClusterIP,后续步骤就和接口名无关了


欠缺微服务改造带来的限制

需要特别指出的是,DNS通用寻址方案虽然可以解决使用接口名访问和支持单进程多接口的问题,但是这种方案只是完成了“寻址”,也就是打通端到端的访问通道。由于应用没有进行微服务改造,部署上是依然一个应用(体现为一个进程,在k8s上体现为一个Service)中包含多个接口,本质上:

  • 服务注册依然是以应用名为基础,对应的k8s service和service上的label也是应用级别
  • 因此提供的服务治理功能,也是以k8s的Service为基本单位,包括灰度,蓝绿,版本拆分等所有的Vesion Based Routing功能
  • 这意味着,只能进行应用级别的服务治理,而不能继续细分到接口级别


这个限制来源于应用没有进行微服务改造,没有按照接口将应用拆分为多个独立的微服务,因此无法得到更小的服务治理粒度。这也就是我在2018年上半年,蚂蚁金服决定基于 Istio 订制自己的 ServiceMesh 解决方案,在6月底对外公布了 SOFAMesh,详情请见之前的文章: 大规模微服务架构下的Service Mesh探索之路 。

DNS通用寻址方案总结

我们将这个方案称为”DNS通用寻址方案”,是因为这个方案真的非常的通用,体现在以下几个方面:

  • 对使用者来说,通过域名和DNS解析的方式来访问,是非常简单直白而易于接受的,同时也是广泛使用的,适用于各种语言、平台、框架。
  • 这个方案延续了k8s和istio的做法,保持了一致的方式方式,对用户提供了相同的体验
  • 这个寻址方案,不仅仅可以用于Dubbo、SOFA、HSF等RPC框架往Service Mesh的迁移,也可以适用于基于HTTP/REST协议的SOA应用,甚至最传统的web应用(例如tomcat下部署多个war包)迁移到Service Mesh
  • 我们也在考虑在未来的Serverless项目中,将Function的寻址也统一到这套方案中,而无需要求每个Function都进行一次服务注册


概括的说,有了这套DNS通用寻址方案,不管需要寻址的实体是什么形态,只要它部署在Service Mesh上,满足以下条件:

  1. 有正常注册为k8s Service,分配有ClusterIP
  2. 为实体(或者更细分的子实体)分配域名或子域名,然后添加到DNS,解析到ClusterIP


那么我们的DNS通用寻址方案,就可以工作,从而将请求正确的转发到目的地。而在此基础上,Service Mesh 所有的强大功能都可以为这些实体所用,实现我们前面的目标:在不修改代码不做微服务改造的情况下,也能提前受益于Service Mesh带来的强大服务治理功能。

— END —

目录
相关文章
|
6月前
|
安全 虚拟化
在数字化时代,网络项目的重要性日益凸显。本文从前期准备、方案内容和注意事项三个方面,详细解析了如何撰写一个优质高效的网络项目实施方案,帮助企业和用户实现更好的体验和竞争力
在数字化时代,网络项目的重要性日益凸显。本文从前期准备、方案内容和注意事项三个方面,详细解析了如何撰写一个优质高效的网络项目实施方案,帮助企业和用户实现更好的体验和竞争力。通过具体案例,展示了方案的制定和实施过程,强调了目标明确、技术先进、计划周密、风险可控和预算合理的重要性。
121 5
|
4月前
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
2月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
2月前
|
算法 前端开发 定位技术
地铁站内导航系统解决方案:技术架构与核心功能设计解析
本文旨在分享一套地铁站内导航系统技术方案,通过蓝牙Beacon技术与AI算法的结合,解决传统导航定位不准确、路径规划不合理等问题,提升乘客出行体验,同时为地铁运营商提供数据支持与增值服务。 如需获取校地铁站内智能导航系统方案文档可前往文章最下方获取,如有项目合作及技术交流欢迎私信我们哦~
151 1
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
企业级API集成方案:基于阿里云函数计算调用DeepSeek全解析
DeepSeek R1 是一款先进的大规模深度学习模型,专为自然语言处理等复杂任务设计。它具备高效的架构、强大的泛化能力和优化的参数管理,适用于文本生成、智能问答、代码生成和数据分析等领域。阿里云平台提供了高性能计算资源、合规与数据安全、低延迟覆盖和成本效益等优势,支持用户便捷部署和调用 DeepSeek R1 模型,确保快速响应和稳定服务。通过阿里云百炼模型服务,用户可以轻松体验满血版 DeepSeek R1,并享受免费试用和灵活的API调用方式。
306 12
|
3月前
|
存储 人工智能 并行计算
2025年阿里云弹性裸金属服务器架构解析与资源配置方案
🚀 核心特性与技术创新:提供100%物理机性能输出,支持NVIDIA A100/V100 GPU直通,无虚拟化层损耗。网络与存储优化,400万PPS吞吐量,ESSD云盘IOPS达100万,RDMA延迟<5μs。全球部署覆盖华北、华东、华南及海外节点,支持跨地域负载均衡。典型应用场景包括AI训练、科学计算等,支持分布式训练和并行计算框架。弹性裸金属服务器+OSS存储+高速网络综合部署,满足高性能计算需求。
|
4月前
|
机器学习/深度学习 传感器 人工智能
穹彻智能-上交大最新Nature子刊速递:解析深度学习驱动的视触觉动态重建方案
上海交大研究团队在Nature子刊发表论文,提出基于深度学习的视触觉动态重建方案,结合高密度可拉伸触觉手套与视觉-触觉联合学习框架,实现手部与物体间力量型交互的实时捕捉和重建。该方案包含1152个触觉感知单元,通过应变干扰抑制方法提高测量准确性,平均重建误差仅1.8厘米。实验结果显示,其在物体重建的准确性和鲁棒性方面优于现有方法,为虚拟现实、远程医疗等领域带来新突破。
123 32
|
4月前
|
Serverless 对象存储 人工智能
智能文件解析:体验阿里云多模态信息提取解决方案
在当今数据驱动的时代,信息的获取和处理效率直接影响着企业决策的速度和质量。然而,面对日益多样化的文件格式(文本、图像、音频、视频),传统的处理方法显然已经无法满足需求。
189 4
智能文件解析:体验阿里云多模态信息提取解决方案
|
4月前
|
文字识别 开发者 数据处理
多模态数据信息提取解决方案评测报告!
阿里云推出的《多模态数据信息提取》解决方案,利用AI技术从文本、图像、音频和视频中提取关键信息,支持多种应用场景,大幅提升数据处理效率。评测涵盖部署体验、文档清晰度、模板简化、示例验证及需求适配性等方面。方案表现出色,部署简单直观,功能强大,适合多种业务场景。建议增加交互提示、多语言支持及优化OCR和音频转写功能...
191 3
多模态数据信息提取解决方案评测报告!
|
6月前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
364 3

相关产品

  • 云解析DNS
  • 推荐镜像

    更多