高德启动Go业务建设已经有段时间了,主要包含Go应用落地,Go中间件建设,云原生三个部分。经过持续的发力,在这些方面取得了不错的进展。高德Go业务落地过程是如何实现的,遇到过哪些问题,如何解决?本文将为大家介绍相关经验,希望对感兴趣的同学有所帮助。
现在高德内主流的语言还是Java,Java应用最多,机器数十分惊人。而且高德整体业务也在快速向前奔跑,成本增加的速度非常快。在减少机器负载方面,Go语言在语言级别对Java语言有相当优势。减少机器成本是我们落地Go应用的第一个考虑因素。
其次,Go语言近几年发展势头迅猛,不论是阿里集团内部,还是在高德内部,对使用Go语言的呼声越来愈高。落地Go应用可以很好的验证Go中间件的稳定性。当然我们可以通过混沌工程等手段去验证,但经过生产环境考验才最具有说服力。验证沉淀Go语言中间件稳定性是我们落地Go应用的第二个考虑因素。
最后,Go语言作为云原生基础框架使用较多的语言,提前落地Go应用,对后续落地云原生可以减少不少阻力。高德目前落地的Serverless/Faas规模相当大。落地Go应用的第三个考虑因素是为后续云原生落地铺路。
本文所述中提到的高德渲染网关,是我们落地的Go应用中业务流量、改造难度、风险,收益均处前列的应用。渲染网关在接入层,占高德总流量的一半,重要性可想而知。
接下来简要介绍下渲染网关承接的业务,方便大家有一些更立体的认识。
渲染网关承接高德手机App、车机、开放平台等来源所有的图面渲染。大家在使用高德时,看到的建筑物、地形图、名称、路线、地铁站、公交站、红绿灯等等所有图面,都是由渲染引擎通过渲染网关透出到端。下面放几张图,方便大家有一些更感性的认识。
上面图一为行前,图二为行中,图三为打车页面,图四为景区手绘图。渲染网关涉及业务众多,以上仅为举例,其他业务就不在这里贴图了。
做过重构项目的同学相信都深有体会,重构项目中最大难点有二,一是要保证业务正确性,二是要保证服务稳定性。
对于保证业务正确性,一般来说,重构的服务大多数为老服务,老服务面临的最大问题是历史逻辑复杂,人员更迭,文档缺失,这些因素都是重构过程中的“拦路虎”。
渲染网关重构同样如此,它涉及高德手机端、车机端、开放平台、打车等各个业务线,所有的历史版本,再加上上述因素,所以保证业务正确性是一件非常困难的工作。
对于保证服务稳定性,做过网关的同学应该都知道,网关本身的属性就决定了它并不会有频繁的业务迭代,稳定性是网关的第一诉求。我们要保证,无论外部环境/依赖是否正常,网关始终能保持高可用。由于Go版本中间件缺乏在大流量场景的充分验证,这一难点需要仔细评测,用合适的方法和手段,尽可能的在仿真环境里验证各种边界情况,从而保证在生产环境不出问题。
在重构高德渲染网关时,我们整体技术方案分三大步走:
如何验证新服务的业务正确性呢?我们采用了线上流量对比的方式。
我们前期做了大量调研,希望找到一个满足(近)实时,二进制级对比的工具,但可惜并没有找到一个满足要求的工具。由于渲染业务的特殊属性,渲染网关绝大多数接口返回的是二进制矢量数据,所以理想的工具不仅要能支持常规数据对比,也要能支持二进制级对比。
二进制级对比的另一个好处是,可以排除字符集差异,不同语言库函数差异。更能保证对比的准确性。有些同学可能会想到打日志,然后离线读取比较的方式来做对比,这种方式有很多弊端。
首先,流量无法重放至指定机器。其次,这种使用方式一般为固定语料,语料完整度不够,不能完全模拟线上环境。此外,打日志对比带来的字符集和语言库函数差异,会对比较准确性有较大影响,特别是对于特殊字符(当7层协议为二进制协议时更加明显)。没有现成的称手工具,怎么办?"逢山开路,遇水搭桥"。
我们自主研发了一款(近)实时流量对比工具,它保障了此次重构的业务正确性,并且还能服务于高德其他业务的重构。其技术细节对TCP/IP涉及较多,非常有意思,感兴趣的同学可以直接跳至《流量对比工具(ln)技术细节》一节。
做服务的同学相信都深有体会,想让服务保障做到5个9的可用性并不是一件容易的事。真实生产环境中可能会出现各种情况,我们要想办法验证各种边界情况下服务的稳定性,才能保障服务高可用。对于重构完成的新服务,更需要一个仿真环境,进行各种情况验证。
构建仿真环境,我们需要保持机器基线、**外部依赖、**外部流量均一致(比如从线上引流)。仿真环境不仅要提供正常态环境的能力,更要能提供异常态环境的能力。
异常态包括断网,网络丢包等等。有句话说的好:20%的代码完成功能,80%的代码来处理各种异常情况。我们在实践中构建异常态的主要手段为混沌工程,通过混沌工程模拟下至操作系统级的异常(如断网,丢包等),上至应用层的异常(如消息中间件积压,JVM方法前后Hook模拟业务异常等等)。
在仿真环境里,同时进行长时间极限压测,语料从线上导流,压测在正常态,异常态均进行,观察服务在一段较长时间内的表现,从而得出服务的稳定性,可用性结论。
观测指标包括基础指标,例如CPU、磁盘利用率、内存利用率、连接数,以及业务指标,例如业务接口成功率、成功量、总量、TP99。通过这种方式,基本上完全覆盖了可能出现各种情况,充分保证了服务稳定性和高可用。
前边讲了如何保证业务正确性和服务稳定性。接下来说说如何保证平滑灰度切流。牢牢遵守阿里发布三原则是平滑灰度切流的“法宝”:可灰度,可监控,可回滚。
在具体实践中,我们按照如下步骤灰度切流:
a. 原Java集群不动,新申请一套Go集群。修改路由规则,部分白名单用户使用Go集群服务。
b. 逐个接口修改路由规则至Go集群,慢慢灰度,期间密切观察机器姿态,业务日志,监控指标。如有异常一键切回至Java集群。
c. 接口全量切至Go集群后,Java集群/Go集群同时共存一段时间。
d. 逐渐下掉Java集群机器。
第一个重要收益:降本提效。高德渲染网关由Java换成Go语言之后,机器数减少近一半。用原来一半的资源完成了相同的工作,大大降低了成本,提高了资源利用率,更好支持了业务发展,大大降低了业务流量快速增长带来的接入层机器增长速度。
第二个重要的收益是:验证了高德与集团合作共建的Go版本中间件的稳定性,一定程度上完善繁荣了集团Go生态。在大流量场景考验过后,高德与集团合作共建的Go版本中间件稳定性得到了相当充分的验证。
第三个重要的收益是:为网关云原生化铺路。网关Go化只是第一步,Go是云原生基础设施实现使用较多的语言,第一步抹平语言差异,对于网关后续云原生化,好处多多,可降低改造风险和成本。
当然,高德渲染网关重构过程中还有许多非常有用的工具沉淀。可为后续业务重构提供关键性保障,比如自研的流量对比工具ln。
先提一个问题,做一款(近)实时流量对比工具需要完成哪些功能?没错,就是流量复制,流量解析,流量重放,流量比对。其实不止这些,在实践中更多是一个流量回归闭环,如下图:
为了支持所有的7层协议,流量获取必须从3层或4层开始。有同学会立马想到tcpdump。没错,就是tcpdump。tcpdump出的文件就是实实在在的流量。复制流量这一步已经有着落了,至于实时,可以两到三个进程错开时间,时间段首尾互相重叠即可完成实时。
另外,设计此工具的另一个考量点是,对线上机器不能有太重的负载,避免对线上机器产生稳定性影响。此种流量复制方式非常轻量,对线上机器增加的负载非常小,可以忽略不计。
流量上传和流量拉取均使用内部文件服务。
流量对比为了保证对比的严谨性,排除可能的字符集干扰/不同库函数实现干扰,我们原生支持了二进制流对比。
回归流量时,可能会发现部分流量比对不一致,这时我们希望只重放特定流量到指定机器,以便于Debug或其他操作,ln原生支持了此功能。
流量解析非常有意思,这种单纯的快乐来自于对网络协议的"把玩"。
实际做法就是如何解析tcpdump文件,拿到tcp payload,还原出http请求。
这里有两个关键点,一是我们如何从tcpdump文件中拿到tcp payload,二是我们如何把四层的tcp payload重新聚合成七层的http请求。
先说如何从tcpdump文件拿到tcp payload,如果能知道tcpdump文件的格式,不就可以知道tcp payload在哪个位置,长度如何了么?这一趴我们就来看看tcpdump文件格式。
先看tcpdump文件总览
文件头的格式和长度都是固定的,如下:
我们可以在读取tcpdump文件后,往后移动23字节,然后开始处理每个数据包。每个数据包的格式如下:
我们处理每个数据包,将前边的包头,数据链路头,ip层头,tcp协议头依次跳过,最终偏移到tcp payload第一个字节位置。其中的更多实现细节(不同层的头字段值的判断,不同长度的判断,大小端的判断,请求数据包与响应数据包如何对应等等)在此不再展开。这里只介绍大体思路,感兴趣的同学可以深挖网络协议。
这一部分介绍如何将tcp payload还原成http请求(此处http指http1.0/1.1,不含http2),ln工具中的完整实现是由tcp payload还原出请求及对应的响应,此处为了便于理解,仅讲解如何解析http请求。解析出http请求实际上已可以重新分别请求新老服务,对比响应二进制流。
一条tcp连接,多个payload发送(这里仅做示意,判断丢包重发等诸多情况属于代码细节,在此不再展开)。可能多个payload对应一个http请求;也可能一个payload的前一部分对应一个http请求,后一部分对应另一个http请求。我们要做的就是把多个payload形成的字节流读入,按http帧的格式,聚合http请求即可。另外,http2的请求不能按这种方式聚合。
由于Go语言和Java语言的内存管理机制不相同,在内存的申请,释放开销也有差别。
对于Go语言来说,sync.pool是复用内存的一把利器。sync.pool优点有许多,比如减少内存的申请,减少了系统调用,减少了gc的压力。但事物都有两面性,sync.pool同样如此,我们在使用sync.pool的时候需要注意,存放在sync.pool里的对象会在不通知的情况下被回收掉,所以类似数据库连接等资源不适合使用sync.pool。
总之,sync.pool可以复用内存,减少机器负载,非常适合临时对象。
Go语言Byte类型为无符号,Java语言Byte类型为有符号,在Java服务迁移Go服务过程中,Java代码中Byte类型正、负、零的比较要注意。
字节切片转字符串
func Bytes2String(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
字符串转字节切片
func String2Bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}
使用此种方式转换,性能很高。原因在于底层无新的内存申请与拷贝。但是不论是字节切片转字符串,还是字符串转字节切片,字节切片中的值更改都会影响字符串的值,使用者要根据业务逻辑判断能否接受,要更精确的把控生命周期。
对于网关来说,耗CPU比较多的一部分是Hash函数/编解码函数/加解密函数/序列化反序列化函数等。在实践中我们重写了相关的库函数,在CPU负载上做了大量优化。
想要降低CPU负载,我们得先知道CPU是如何工作的,才能知道如何写代码会更好的降低CPU负载。这里会介绍粗略的CPU工作原理。
放张CPU 流水线工作步骤图
主要优化MEM步骤,利用CPU缓存尽可能减少MEM步骤所占时钟周期,从而降低CPU负载。
类似NUMA架构,affinity等降低CPU负载的方式也是同样的思想,尽可能减少Load数据所需的时钟周期。
对于优化Golang库函数来说,可以提升的点有两个:优化算法本身;优化CPU缓存亲和度。
我们专注于第二种,拿base64编解码函数举例,传入的Byte切片与返回Byte切片,底层并非为同一数组,同一内存。这中间就涉及两块可以额外消耗CPU时钟周期的点,一是内存的申请与释放,二是两块内存分别访问带来的CPU缓存争用问题(与伪共享不完全一样)。
如果我们复用传入的内存呢?即边解码边覆写同一块内存。美妙的事情发生了,上边所说的问题不存在了。用更少的时钟周期完成了一样的工作。需要注意的是,由于函数的输入和输出使用同一块内存,对程序开发者来说有更高的编码要求,即对数据在程序中流转的生命周期有更精准的把控力,代码要打磨的很细致。
网关的下一步是云原生化,采用Service Mesh方式实现。这可以解决目前中心化网关的弊端,去中心化可以提升接入层稳定性,减少爆炸半径,增强隔离能力,实现更精细粒度的管控。
其次,降低机器成本,按照目前内部压测及业界已有的实践压测结论,Mesh化后成本会进一步减少,考虑到现有RPC框架本身的消耗,成本会进一步缩减。且数据面代理也在不断优化中,后续性能表现会更优异,额外两跳对机器的负载将进一步下降。
再有,网络层能力集大大增强。网关Mesh化,可以带动上游业务Mesh化,最后在整个网络层做一个能力超集。
现有的Service Mesh框架提供的能力可以概括为Connect,Secure,Control,Observe四大部分,其能力是现有网关能力的超集,可以做到之前做不到的事情,最明显的是Observe能力带来的好处,可大大加强全链路服务可观测性,这于对后续开展服务稳定性,全链路故障快速定位等工作有极大帮助。
以上要做的事情任重而道远,另外我们在会做更多云原生的试点和落地,技术同学都清楚,从技术选型到技术原型,再到实际业务落地,中间有很长的路要走。但路选对了,就不怕远。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/fsOg1AFuKh7Wsurrh_MYdw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。