作者:纳海
端云互联最佳实践:https://help.aliyun.com/document_detail/200032.html
背景
在云原生时代,国内外众多云厂商释放出强大的技术红利,如何利用廉价、稳定且高效的云设施是当今的一个主要命题。在云上,我们可以很方便地创建虚拟网络、虚拟机、数据库、消息队列等基础设施和中间件,也可以使用容器服务、EDAS、SAE、函数计算等PaaS和Serverless服务来减轻应用管控的压力。
但事情并不是一帆风顺的。应用上云已是历史大潮不可阻挡,但随之而来开发者很快就体会到上云的另一面:由云上和云下网络不通所带来的开发体验割裂感。在上云之前,开发者可以在本地完成代码开发、测试、联调等开发流程闭环;而上云之后,数据库、缓存、消息队列和其他微服务应用都部署在云上的虚拟网络之中,我们再无法在本地完成开发流程。
如果是中东土豪,他可能会考虑使用物理专线来打通网络。因为他只需支付光纤铺设费、楼内光缆租赁费、端口占用费、流量费等百万量级的钱,同时说服安全团队来允许完全打通环境而已。
如果是专业运维人员,他可能会考虑搭建VPN来打通网络。当他花费精力搭建VPN服务器,发现同事们还是用不起来,纷纷抱怨:
- “一打开VPN,整个本地系统网络流量都转发到云端了,其他事情干不了啦!”
- “除了配置VPN,还要配置应用运行参数,太麻烦了!”
- “云端服务怎么调用不了本地服务,云端网络路由添加了吗?”
- ...
看到这些问题,运维小哥内心也感到心累...
而现在,我们提供了一个开箱即用的插件工具,无需你花费大量的金钱或者人力。你所需要的只是在IDE中一键开启开关,然后通过IDE所启动的应用就能访问到云端环境里的数据库、MQ、缓存和其他微服务。所有的事情都由插件来帮你完成。
介绍
这款工具是我们自主研发的“端云互联”插件,“端”指的是开发端,“云”指的是云上网络,通过某种方式实现“端”和“云”的双向互通,并且没有传统VPN的问题。
端云互联功能集成在Alibaba Cloud Toolkit(简称ACT)这个上云工具产品中,并支持Intellij IDEA和Eclipse两款IDE。你只需在插件市场中搜索“Alibaba Cloud Toolkit”进行安装即可,例如在Intellij IDEA中搜索如下:
我们在2018年就开始了端云互联项目的研发,这个过程中迭代了大大小小的版本,共经历了三个里程碑,至今有数十万人次的使用。下面来介绍它的特性支持和实现原理。
端云互联1.0
1.0阶段解决了本地和云端双向互联的问题,使得本地服务不仅仅可访问云端资源,还可以跟云端服务互相通信。
双向互联
以下为端云互联的核心架构,整体分为两个模块:通道服务和代理机。
其中,模块功能如下:
- 代理机:负责云端的流量转发。端云互联方案对代理机的要求很低,一台普通规格的ECS就可以充当“乞丐版”的代理机。并且,Debian、Ubuntu、Redhat等Linux系统已经包含端云互联所依赖的底层库,无需额外安装其他软件。
- 通道服务:负责本地的流量转发。当我们打开端云互联开关并启动应用时,插件会在本地拉起一个通道服务进程。这个进程的职责非常简单,它只负责本地应用和云端代理机之间的流量转发,无其他操作。
通道服务和代理机之间是使用加密通道来通信的,中间人无法窃取通道中的数据。而在微服务应用中,我们结合Java原生的代理参数和自研的流量拦截方案来将应用的流量转发至通道服务。
开发人员在IDE中启动应用时,端云互联插件会自动拉起通道服务,并注入相关参数至应用中。启动后,应用流量自动转发至通道服务,无需人工干预。
从架构上来看,端云互联跟VPN有点类似,都分为服务端和客户端。但实际上,两者有很大的差异,下图进行了对比总结:
其中,在“云端访问本地”这一点上,虽然两者都支持,但具体原理并不相同。如果采取VPN方案,那么其他云端服务访问本地服务时,需要手动配置网络路由,否则网络不可达。而端云互联通过改造微服务框架,可使得云端服务调用代理机,再通过代理机转发到本地应用中,无需设置网络路由。在易用性和安全性上,端云互联都优于VPN。
端云互联2.0
在1.0阶段,我们实现了本地和云端的双向互通,这满足了最基本的开发需求。在实际业务中,客户提出了更高的要求。
我们一个客户有庞大的研发团队,他们都使用端云互联进行开发,但在联调时发现一个问题:研发人员A发起的服务调用有时候调到别的节点去了,没有到所期望的研发人员B的本地节点上。这个问题是由于微服务框架的路由机制引起的,当环境中一个服务存在多个节点时,会使用随机(或轮流)算法来进行调用。微服务模块越多,链路越长,这个问题就越严重。
在2.0中,我们提供了多人精准联调能力,此能力可使得服务请求“指哪打哪”,可大幅提高服务联调效率。除此之外,我们还提供基于代理的远程调试能力,方便本地对云端环境中的微服务节点进行调试,提高调试效率。
同时,通过横向产品支持,端云互联2.0可服务于云原生产品EDAS、SAE和MSE等开发者,受到广泛好评。
多人精准联调
下图描述了多人联调的一个典型场景:
小王负责服务A,小张负责服务B,在一次需求迭代中他们完成了代码开发,正在进行联调。由于微服务框架使用随机(或轮流)策略进行调用,导致了两个问题:
- 测试同学小马正在环境中进行功能测试,测试请求调用到小王和小张的本地节点上来了,导致测试不符合预期;
- 小王发起的测试请求调到其他节点去了,没到他和小张的节点上,联调效率很低;
通过多人精准联调能力,可以使得只有小王发起的请求调到他的本地节点和小张的本地节点,而测试小马的请求只在云端稳定环境中调用。
小王和小张需要做的事情比较简单,他们只需要在控制台开启全链路流控功能,创建一个用于测试的流控环境。流控环境可配置请求识别规则,可通过Cookie、Header、请求参数等维度来判断是否为测试请求,如果判断通过则将请求调用到该环境中的节点中去。
然后小王和小张在IDE中将本地节点添加到这个测试环境中去即可,如下所示:
这样配置完成后,那么只有符合特征的请求才会调用到小王和小张的节点,下图中只有Header包含“测试”的请求才会到他们节点中:
远程调试
远程调试(Remote Debug)一直都是排查问题的重要手段,但在云原生环境里远程调试并不是一件简单的事情。这是因为在默认情况下云上的微服务节点通常不能被公网访问,如果需要进行远程调试,我们需要对目标节点开放公网访问,并且设置安全策略以放通调试端口流量。
如果当前有A,B,C三个服务,每个服务有3个节点,那么我们需要分别建立3个安全组,并绑定9个公网网卡到机器节点。如下所示:
这种方式存在以下问题:
- 浪费成本:每个微服务节点都需要绑定公网网卡,成本跟测试节点数成正相关。
- 配置复杂:在云上往往采取弹性伸缩的策略来维护机器节点,达到“用时即建,用完即放”的按需使用目的。而每当创建新的机器节点我们都需要单独配置公网网卡和安全组,使用上较繁琐。
- 存在安全性隐患:如果微服务节点都对外暴露公网访问,会存在较大的安全风险。
甚至在有些场景下,由于安全要求内网机器节点不允许挂载公网网卡。对于这些问题,端云互联支持基于代理的远程调试,如下所示:
调试请求通过通道服务来转发给代理机,再由代理机转发至目标调试节点。通道服务和代理机之间的通道是加密的。对于安全要求非常严格的场景,可以使用安全组(或白名单)策略来进一步提高代理机的安全水位。
在使用上,你只需配置Alibaba Cloud Remote Debug,配置内容跟IDE自带的远程调试配置基本相同,但支持使用代理进行连接,如下所示:
其中有如下配置项:
- Proxy:指定云端代理机。当运行时,插件会自动拉起通道服务连接代理机,无需人工干预。
- Host:指定远程调试的目标机器节点IP。图中为172.16.0.1。
- Port:指定远程调试的目标机器调试端口。图中为5005。
云原生产品支持
端云互联2.0支持了阿里云上微服务领域三大产品,EDAS(企业级分布式应用服务)、SAE(Serverless应用引擎)和MSE(微服务引擎)。这三个产品都支持微服务治理能力,满足不同的企业需求,产品特性如下:
- 企业级分布式应用服务 EDAS(Enterprise Distributed Application Service):是应用全生命周期管理和监控的一站式 PaaS 平台,支持部署于 Kubernetes/ECS,无侵入支持 Java/Go/Python/PHP/.NetCore 等多语言应用的发布运行和服务治理 ,Java 支持 Spring Cloud、Apache Dubbo 近五年所有版本,多语言应用一键开启 Service Mesh。
- Serverless 应用引擎(Serverless App Engine,简称 SAE):实现了Serverless 架构 + 微服务架构的完美融合,真正按需使用、按量计费,节省闲置计算资源,同时免去 IaaS 运维,有效提升开发运维效率。SAE 支持 Spring Cloud、Dubbo 等流行的微服务架构,支持控制台、Jenkins、云效、插件等部署方式。除了微服务应用外,您还能通过 Docker 镜像部署任何语言的应用。
- 微服务引擎(Micro Service Engine,简称MSE):是一个面向业界主流开源微服务生态的一站式微服务平台, 帮助微服务用户更稳定、更便捷、更低成本的使用开源微服务技术构建微服务体系。提供注册中心、配置中心全托管(兼容Nacos/ZooKeeper/Eureka)、网关(兼容Zuul/Kong/Spring Cloud Gateway)和无侵入的开源增强服务治理能力。
因此,无论你是EDAS用户、SAE用户还是MSE用户,都可以使用端云互联能力来提高上云的开发效率。在插件上,这三个产品的配置步骤是基本相同的,除了产品自身的差异性以外。配置页如下所示:
在未来,我们会支持阿里云上更多的云原生产品进行互联,同时也会服务于阿里云以外的云原生开发者,敬请期待。
端云互联3.0
2.0版本解决了Java应用跟云端互联互通的问题,很多细节也打磨的比较完善,但它缺乏对容器领域和诊断能力的支持。这些能力我们在3.0阶段进行了补齐。
如果你是Kubernetes用户,那么可以使用3.0插件的Kubernetes代理能力,无需额外配置云端代理机。
如果你是非Java语言用户,或者对应用运行环境有一定要求,那么可以使用3.0插件的容器级互联能力,来在本地使用Docker运行应用。在Docker容器中,应用可以正常访问云端服务和资源,流量自动通过代理来转发。
如果你对本地运行应用所发生的调用异常感到无从下手,那么可以使用3.0插件的本地链路诊断能力,我们会统一收集本地应用的调用链路,调用异常一目了然。
下面来具体介绍这些特性。
Kubernetes代理
3.0版本的Kubernetes代理能力可基于Kubernetes集群自动打通代理通道。
在面向Kubernetes的开发中,我们可以通过kubectl命令和kubeconfig配置文件来跟API Server进行通信,并访问集群中的容器。API Server会对请求进行身份认证、鉴权和加密处理。如果开放API Server的公网访问,那么我们在本地通过kubectl执行交互式命令时,此时API Server将充当中间代理角色,如下所示:
基于此特性,端云互联3.0插件在应用启动时,调用kubectl临时创建一个代理容器。通过结合API Server和临时代理容器进行打通,本地应用可访问云端服务和其他资源。整体链路如下所示:
代理容器占用64MB ~ 128MB的节点内存,并在本地应用停止时自动删除。
而在插件配置上也非常简单,你只需在插件中设置kubeconfig配置文件和选择Kubernetes命名空间:
在启动本地应用时,插件使用该kubeconfig配置文件来调用kubectl创建临时容器,并进行通道打通和流量转发。在终止应用时,插件使用该kubeconfig配置文件来调用kubectl删除该临时容器。
容器级互联
容器级互联是指,本地会启动Docker容器,并在容器内运行你的微服务应用,微服务应用可跟云端环境进行互联。如果你存在如下场景,那么容器级互联是你的最佳选择:
- 非Java语言应用;
- 应用运行时对操作系统存在特定要求;
在此模式下,微服务应用和通道服务都使用容器来运行,整体交互如下:
在实现层面上,容器级互联基于iptables来拦截和转发流量到代理容器中的通道服务,通道服务再将数据通过云端代理转发至目标地址。在架构上,这种模式跟Service Mesh的Sidecar模式有点类似,应用容器把流量转发给通道服务容器(sidecar容器)。不过端云互联的通道容器只是做数据的透明转发,而Service Mesh的sidecar可进行微服务发现和治理的能力,这一点有所不同。
在使用上,插件运行容器的Alibaba Microservice Container配置,交互如下所示:
如果你在应用容器中运行的是Java语言应用,插件还支持快捷的应用调试,无需额外设置具体参数。启动应用时,插件会通过环境变量注入JDWP调试参数,以打开调试端口。插件进一步结合Intellij IDEA的智能检测,可通过Attach debugger来一键调试容器中的Java应用,如下所示:
由图可见,插件会将容器中应用的日志输出打印在IDE窗口中,日志中的“Listening for transport dt_socket at address: 5005”表示容器中的Java应用已打开调试端口。点击Attach debugger,IDE将会连接到容器中Java应用的调试端口,接下来便可进行代码调试,如下所示:
本地链路诊断
在开发过程中,你是否遇到过这个场景:下游服务接口返回了500,你只知道接口调用失败了,但具体原因并不知晓?找该模块研发人员来排查时,他过了半天回复一句“现在有点忙,待会我看看”?等他有空排查后,发现问题出在另一个模块,让你去找另一个同学来排查?...
诸如此类的场景在开发过程中屡见不鲜,往往一个小问题要花费大量精力和时间来进行排查。这个场景是链路追踪技术的典型场景。现在,我们把链路追踪也集成到端云互联能力上,使得本地调用链路也能上报到云端,当出现异常时问题一目了然。
比如,当前环境中有交易中心、商品中心和库存中心三个服务,你正在和测试同学验证新版本特性。测试同学在页面测试下单流程时,发现下单失败,如下所示:
由于涉及模块多,问题排查耗时非常长。端云互联3.0插件集成了ARMS(应用实时监控服务)的Java Agent,它通过代码无侵入的埋点机制来收集调用链路上的信息并上报到ARMS服务端进行统一收集和智能分析。出现异常时,只需在云端根据TraceId来查询调用链路,问题了然于胸:
TraceId是用于链路追踪底层的概念,从前端页面开始生成并透传至下游各节点。为方便使用,插件还提供了打印本地链路的开关,开启后将会输出本地应用服务调用链路的相关信息,如下所示:
链路输出中包含如下信息:
- TraceId:用于标记请求的整体处理过程。在分布式微服务调用场景下,TraceId会从最前端的应用节点透传至下游链路各个节点,可根据此TraceId在EDAS控制台或ARMS控制台查询整体链路处理过程。
- Service:当前应用的请求处理入口,如Spring Cloud服务、Dubbo服务、HSF服务等。
- API:链路处理过程中的方法签名。
- Line:方法处理的具体行数。
- Cost:此方法及其下游处理的耗时,单位毫秒。
- Ext:扩展信息,包含请求处理状态码、数据库访问SQL、资源目标地址等信息。
- Console link:ARMS控制台上收集的此链路信息,可点击此链接直接查看全链路信息。
点击Console link链接,可查看此请求的上下游处理链路,如下所示:
我们还可以进一步查看每个服务内的处理详情:
看到这里,是不是感觉排查问题有更多思路了呢:)
写在最后
云原生浪潮浩浩荡荡不可阻挡,业务上云也是企业的必经之路。但上云从来都不是一片坦途,在此过程中我们总会遇到一些困难和挑战。得益于云原生技术的日益成熟,这些问题一定会有相应的解法。
在开发态这一领域,我们是国内云厂商当中走在前沿的探索者。从2018年开始孵化端云互联1.0版本,到目前2021年的端云互联3.0版本,当中遇到了大大小小的问题和挑战,但最终都一一解决了。此能力为公共云和专有云的开发者带来了极大的便利,使其在本地就可以完成开发、测试和联调闭环。
在未来我们会不断提供更好用、更强大、更易用的云原生工具来服务开发者,敬请期待。
参考资料:
- 端云互联:https://help.aliyun.com/document_detail/200032.html 。
- EDAS(企业级分布式应用服务):https://www.aliyun.com/product/edas 。
- SAE(Serverless 应用引擎):https://www.aliyun.com/product/aliware/product/sae 。
- MSE(微服务引擎):https://www.aliyun.com/product/aliware/mse 。
- ARMS(应用实时监控服务):https://www.aliyun.com/product/arms 。
- Arthas:https://github.com/alibaba/arthas 。