我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:双彩网 > 直接寻址 >

SOFAMesh中的多协议通用解决方案x-protocol介绍系列(1) : DNS通

归档日期:06-13       文本归类:直接寻址      文章编辑:爱尚语录

  2018年上半年,蚂蚁金服决定基于 Istio 订制自己的 ServiceMesh 解决方案,并在6月底正式对外公布了 SOFAMesh,详情可直接点击之前的文章查看:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  因此,以客户端的视角看来,Isito的这个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 匹配!

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

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

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

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

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

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

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

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

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

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

本文链接:http://clinicapetrer.com/zhijiexunzhi/109.html