当前位置:首页 > 公众号精选 > 架构师社区
[导读]1.导读高德启动Go业务建设已经有段时间了,主要包含Go应用落地,Go中间件建设,云原生三个部分。经过持续的发力,在这些方面取得了不错的进展。高德Go业务落地过程是如何实现的,遇到过哪些问题,如何解决?本文将为大家介绍相关经验,希望对感兴趣的同学有所帮助。2.高德为什么要落地Go...

1.导读


高德启动Go业务建设已经有段时间了,主要包含Go应用落地Go中间件建设云原生三个部分。经过持续的发力,在这些方面取得了不错的进展。高德Go业务落地过程是如何实现的,遇到过哪些问题,如何解决?本文将为大家介绍相关经验,希望对感兴趣的同学有所帮助。


2. 高德为什么要落地Go应用


现在高德内主流的语言还是Java,Java应用最多,机器数十分惊人。而且高德整体业务也在快速向前奔跑,成本增加的速度非常快。在减少机器负载方面,Go语言在语言级别对Java语言有相当优势。减少机器成本是我们落地Go应用的第一个考虑因素。


其次,Go语言近几年发展势头迅猛,不论是阿里集团内部,还是在高德内部,对使用Go语言的呼声越来愈高。落地Go应用可以很好的验证Go中间件的稳定性。当然我们可以通过混沌工程等手段去验证,但经过生产环境考验才最具有说服力。验证沉淀Go语言中间件稳定性是我们落地Go应用的第二个考虑因素。


最后,Go语言作为云原生基础框架使用较多的语言,提前落地Go应用,对后续落地云原生可以减少不少阻力。高德目前落地的Serverless/Faas规模相当大。落地Go应用的第三个考虑因素是为后续云原生落地铺路。


3. 大流量场景Go应用落地


3.1 渲染网关介绍

本文所述中提到的高德渲染网关,是我们落地的Go应用中业务流量、改造难度、风险,收益均处前列的应用。渲染网关在接入层,占高德总流量的一半,重要性可想而知。


接下来简要介绍下渲染网关承接的业务,方便大家有一些更立体的认识。


渲染网关承接高德手机App、车机、开放平台等来源所有的图面渲染。大家在使用高德时,看到的建筑物、地形图、名称、路线、地铁站、公交站、红绿灯等等所有图面,都是由渲染引擎通过渲染网关透出到端。下面放几张图,方便大家有一些更感性的认识。


高德渲染网关Go语言重构实践


上面图一为行前,图二为行中,图三为打车页面,图四为景区手绘图。渲染网关涉及业务众多,以上仅为举例,其他业务就不在这里贴图了。


3.2 重构难点

做过重构项目的同学相信都深有体会,重构项目中最大难点有二,一是要保证业务正确性,二是要保证服务稳定性。


对于保证业务正确性,一般来说,重构的服务大多数为老服务,老服务面临的最大问题是历史逻辑复杂,人员更迭,文档缺失,这些因素都是重构过程中的“拦路虎”。


渲染网关重构同样如此,它涉及高德手机端、车机端、开放平台、打车等各个业务线,所有的历史版本,再加上上述因素,所以保证业务正确性是一件非常困难的工作。


对于保证服务稳定性,做过网关的同学应该都知道,网关本身的属性就决定了它并不会有频繁的业务迭代,稳定性是网关的第一诉求。我们要保证,无论外部环境/依赖是否正常,网关始终能保持高可用。由于Go版本中间件缺乏在大流量场景的充分验证,这一难点需要仔细评测,用合适的方法和手段,尽可能的在仿真环境里验证各种边界情况,从而保证在生产环境不出问题。


3.3 技术方案

在重构高德渲染网关时,我们整体技术方案分三大步走:


高德渲染网关Go语言重构实践


3.3.1 线上流量对比

如何验证新服务的业务正确性呢?我们采用了线上流量对比的方式。


我们前期做了大量调研,希望找到一个满足(近)实时,二进制级对比的工具,但可惜并没有找到一个满足要求的工具。由于渲染业务的特殊属性,渲染网关绝大多数接口返回的是二进制矢量数据,所以理想的工具不仅要能支持常规数据对比,也要能支持二进制级对比。


二进制级对比的另一个好处是,可以排除字符集差异,不同语言库函数差异。更能保证对比的准确性。有些同学可能会想到打日志,然后离线读取比较的方式来做对比,这种方式有很多弊端。


首先,流量无法重放至指定机器。其次,这种使用方式一般为固定语料,语料完整度不够,不能完全模拟线上环境。此外,打日志对比带来的字符集和语言库函数差异,会对比较准确性有较大影响,特别是对于特殊字符(当7层协议为二进制协议时更加明显)。没有现成的称手工具,怎么办?"逢山开路,遇水搭桥"。


我们自主研发了一款(近)实时流量对比工具,它保障了此次重构的业务正确性,并且还能服务于高德其他业务的重构。其技术细节对TCP/IP涉及较多,非常有意思,感兴趣的同学可以直接跳至《流量对比工具(ln)技术细节》一节。


3.3.2 仿真环境压测

做服务的同学相信都深有体会,想让服务保障做到5个9的可用性并不是一件容易的事。真实生产环境中可能会出现各种情况,我们要想办法验证各种边界情况下服务的稳定性,才能保障服务高可用。对于重构完成的新服务,更需要一个仿真环境,进行各种情况验证。


构建仿真环境,我们需要保持机器基线、外部依赖、外部流量均一致(比如从线上引流)。仿真环境不仅要提供正常态环境的能力,更要能提供异常态环境的能力。


异常态包括断网,网络丢包等等。有句话说的好:20%的代码完成功能,80%的代码来处理各种异常情况。我们在实践中构建异常态的主要手段为混沌工程,通过混沌工程模拟下至操作系统级的异常(如断网,丢包等),上至应用层的异常(如消息中间件积压,JVM方法前后Hook模拟业务异常等等)。


在仿真环境里,同时进行长时间极限压测,语料从线上导流,压测在正常态,异常态均进行,观察服务在一段较长时间内的表现,从而得出服务的稳定性,可用性结论。


观测指标包括基础指标,例如CPU、磁盘利用率、内存利用率、连接数,以及业务指标,例如业务接口成功率、成功量、总量、TP99。通过这种方式,基本上完全覆盖了可能出现各种情况,充分保证了服务稳定性和高可用。


3.3.3 平滑灰度切流

前边讲了如何保证业务正确性和服务稳定性。接下来说说如何保证平滑灰度切流。牢牢遵守阿里发布三原则是平滑灰度切流的“法宝”:可灰度可监控可回滚


在具体实践中,我们按照如下步骤灰度切流


a. 原Java集群不动,新申请一套Go集群。修改路由规则,部分白名单用户使用Go集群服务。


b. 逐个接口修改路由规则至Go集群,慢慢灰度,期间密切观察机器姿态,业务日志,监控指标。如有异常一键切回至Java集群。


c. 接口全量切至Go集群后,Java集群/Go集群同时共存一段时间。


d. 逐渐下掉Java集群机器。


3.4 主要收益

第一个重要收益:降本提效。高德渲染网关由Java换成Go语言之后,机器数减少近一半。用原来一半的资源完成了相同的工作,大大降低了成本,提高了资源利用率,更好支持了业务发展,大大降低了业务流量快速增长带来的接入层机器增长速度。


第二个重要的收益是:验证了高德与集团合作共建的Go版本中间件的稳定性,一定程度上完善繁荣了集团Go生态。在大流量场景考验过后,高德与集团合作共建的Go版本中间件稳定性得到了相当充分的验证。


第三个重要的收益是:为网关云原生化铺路。网关Go化只是第一步,Go是云原生基础设施实现使用较多的语言,第一步抹平语言差异,对于网关后续云原生化,好处多多,可降低改造风险和成本。


当然,高德渲染网关重构过程中还有许多非常有用的工具沉淀。可为后续业务重构提供关键性保障,比如自研的流量对比工具ln。


4. 技术干货


4.1 流量对比工具(ln)技术细节

先提一个问题,做一款(近)实时流量对比工具需要完成哪些功能?没错,就是流量复制,流量解析,流量重放,流量比对。其实不止这些,在实践中更多是一个流量回归闭环,如下图:


高德渲染网关Go语言重构实践


4.1.1 流量复制

为了支持所有的7层协议,流量获取必须从3层或4层开始。有同学会立马想到tcpdump。没错,就是tcpdump。tcpdump出的文件就是实实在在的流量。复制流量这一步已经有着落了,至于实时,可以两到三个进程错开时间,时间段首尾互相重叠即可完成实时。


另外,设计此工具的另一个考量点是,对线上机器不能有太重的负载,避免对线上机器产生稳定性影响。此种流量复制方式非常轻量,对线上机器增加的负载非常小,可以忽略不计。


4.1.2 流量上传

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
关闭
关闭