Go语言结合serverless的架构演进之路-Cap

----- CTO视野原创 转载请注明出处 -----

Capital One是美国的一家银行控股和金融企业,在国内通常被称作第一资本金融公司。它的主营业务包括信用卡、汽车贷款、银行和储蓄账户。2019年最新美国银行业排行榜上,它的信用卡业务位居第三。与摩根大通等耳熟能详的大银行相比,Capital One的名气不那么响亮,但却有令人吃惊的成长速度。成立仅短短三十年,它已与这些历史悠久的大银行比肩而立。

很少有银行能像Capital One那样很早地意识到技术驱动的必要性。首席执行官Richard Fairbank强调说[1]:“我们将更多地像科技公司一样思考,也许要有点不像传统银行。”

作为一家技术驱动型金融公司,Capital One为其最盈利的信用卡业务搭建了强有力的技术体系。以下我们根据其开发团队的文章和讲演探究下信用卡推荐业务背后的技术演进之路。

Capital One的信用卡推荐业务是全程在线上完成的过程,从展示推荐、选择优惠、申请、预审核、直到生成合约。在众多合作渠道的网站上,潜在客户也能获得和官网一样的服务。Capital One为这些合作渠道的页面提供一组API(官方称为Credit Offer APIs[2]),页面和API分别由合作渠道和Capital One各自负责开发运维。

业务场景向技术提供了几个方面的挑战:

为了差异化运营的需要,这个API需要为不同渠道和不同定位的客户持续地开发新特性。

开发新特性的同时,快速增长的业务量要求API持续地横向扩展。扩展的服务要为差异化的合作渠道的网络结构提供一致的高性能。

合作渠道页面依赖API,因此API必须不间断地为每个合作渠道服务。各渠道促销活动会带来流量尖峰要求API必须高可用。

信用卡推荐业务首次上线是在2015年,那时候这组API用Java语言构建。2018年完成彻底重构的3.0版本,业务逻辑使用Go编写,基于serverless系统,运行于Amazon AWS提供Lambda云服务平台[3]。

架构演进的起点源自2016年年中的一个新需求。为细化客户特性粒度,业务需要确切知道客户是否看过预审核通过的页面。为此新增API向服务端通知客户端页面结果。这是Go语言第一次被用在信用卡业务。

理论上,Go语言的优势在于高并发性能。这得益于与多数语言在多任务处理内存模型上的不同。其一是goroutine替代thread,其二是基于channel内存模型替代基于shared memory的并发模型。[4]

这两方面的细节是:首先,thread是操作系统管理的资源,单个thread需要大于1MB内存,操作涉及内存管理、寄存器和一级缓存。相比之下,goroutine只存在于语言运行时库的虚拟空间中,而不存在于操作系统层面。三个数据结构G、M和Sched记录资源分配,单个goroutine初始分配内存仅仅2KB。其次,goroutine并发机制是协调式调度,不是系统中断的抢占式调度。当一个goroutine进入等待状态(例如,channel通信、垃圾回收等操作),语言运行时库协调另一个goroutine运行,这个动作不需要切换当前thread,减少系统调度产生的资源消耗。[5]

为了验证,开发团队首先用Go语言开发了一个概念验证版本。与Java开发版本性能比对,Go版本明显地获得巨大的性能提高。基于这个清晰明朗的验证结果,开发团队很快决定将后续开发基于Go语言,并逐渐重构整个Credit Offer APIs。

开发团队主管回忆说,重构过程比预期顺利得多。刚开始时开发团队里还没有一个人懂得Go语言,仅仅一个月后,每个人都在用Go写代码了。作为代码评审的最后一关,这位主管决定是否批准代码合并,是否进入预发布。这个角色必须深入了解代码的业务逻辑。让他惊喜的是,用Go语言重构的业务代码简明易懂,他可以更好地完成这个关键角色的审批职责了。

这位开发团队主管总结说,Go语言的灵活性、易用性以及Go背后真正酷的概念(Go如何处理并发、垃圾收集,还有安全与速度)帮助开发团队在构建过程中更容易地开发业务逻辑。Go语言它通过保持真正简单的语法、标准库和测试支持来实现这一点。

开发团队下一个想探索的技术是serverless。Go语言的一个初衷是快速和简单,这也是Lambda(这里指亚马逊AWS的serverless云服务平台Lambda)的初衷。

开发团队进行了一轮业务架构分析,基本上Credit Offer APIs涉及的业务用例都非常适合封装在serverless框架中,于是决定开始为迁移到serverless做准备。2018年1月初AWS发布了Lambda的Go语言支持,开发团队立即就开始了迁移工作。由于之前比较充分的准备,包括开发分析工具和日志工具,向Lambda封装代码的开发过程顺利推进。特别地,开发团队添加为serverless环境中加上更多的环境相关日志来辅助问题定位。整个迁移在2018年10月初完成。

如上图,开发团队总结了serverless让他们兴奋的四个优势:高可用、灵活扩展、无需管理服务器、无闲置容量。

如前面提到的挑战,CreditOffer APIs的业务特点决定它与渠道商的页面紧密耦合。这种紧密耦合总会带来许许多多的额外开发成本,上线一个新业务不只涉及一家公司,运维协调也更加繁复。一方面上线新业务过程复杂,另一方面服务必须毫不间断,并不断水平扩展支持业务量增长。Serverless云架构很好地满足这两方面的需要,让开发团队不需要开发服务器管理框架功能,这让整体架构更简捷、更有弹性。其中一个最大的收获就是开发人员再也不需要考虑基础设施问题而停下手头的开发,可以投入更多的时间来开发交付与业务相关的功能。

从上面这张图可以看到整体架构清晰简单。在图中,业务逻辑封装在Lamdba中。Capital One API gateway基于AWS提供的API gateway,是这套serverless系统主要的触发事件来源。CloudWatch用以监控业务系统的健康状况。业务系统的存储选择Amazon Dynamodb(AWS的nosql云数据库),它提供较适合业务逻辑的字符转义处理功能,并且灵活的schema也更符合业务特点;S3对象存储服务用来做长期存储。SNS(Simple Notification Service)当出现意外问题时发警报通知客服团队和开发团队。另外这个架构中也使用了外部的New Relic监控系统。整体而言这个基于Lambda架构很简洁,绝大部分业务逻辑都被封装在了AWS云提供的组件之中。稍微复杂的预审核业务API,因为它需要调用外部API。

这套基于AWS的serverless解决方案的另一个关键特点是关于灰度部署。AWS灰度部署功能可以按版本号等多种维度设定部署比例,也可以设定特定的灰度部署事件警报。例如当某个级别的故障发生,部署过程可自动回滚而不用人工干预。基于这些灰度发布工具,开发团队定制了自动化发布流水线(如上图)。首先,代码从GitHub搬运到AWS,经过Jenkins,写入AWS Lambda配置AMS,并存入S3,准备发布。然后,选取5%的Lambda部署新版本,发布成功后按预估的时间格进行循环测试。之后,无紧急缺陷的情况下将继续增量地部署下一组5%的Lambda新版本。具有灰度部署能力的自动化发布流水线为可用性带来很大帮助。

Serverless重构过程的经验教训:

Serverless并不意味完全不需要关心服务器。Serverless做水平扩展很容易,但有一些限制。服务器水位等负载指标是必须被细致地规划和监控的。如果没有细致规划,流量尖峰还是会让服务宕机。所谓细致规划可能涉及规划扩展到不同的地理区域、逻辑区域,不同的可用性级别区域,并定制好扩展的步骤。

上线前做好本地测试。Serverless的一大令人诟病的不足之处是不容易调试。因为Lambda是被事件驱动执行的。开发团队的经验是,在上线前好好利用Amazon Lambda平台提供的本地测试工具。在开发人员的本地电脑上,他们可以完全地模拟出事件并测试Lambda。

根据业务特点选择数据库技术。Serverless框架支持多个数据库技术可以选用。选用哪种取决于业务用例,需要保存怎样的数据,需要保存多长时间等因素。在Captial One的信用卡推荐业务里,nosql和对象存储可以很好地满足需求。

保持简洁。Lambda不应该是一个个巨大的代码块。

使用分布式的Tracing工具。Capital One开发团队用的是AWS的X-Ray。对于AWS环境来说这是一个自然的选择。对于其它云服务环境,Tracing工具的功能大致应该包括:端到端链路跟踪,生成服务调用图、记录性能数据、记录分析服务端和客户端延迟,辅助业务逻辑分析等。

规划灰度部署计划和自动化。做好发布与问题回滚的整体自动化。利用好灰度部署功能。

微服务化相关考虑设计。设计解决方案时,尽量使其单个服务简单化。仔细确定内部外部的依赖关系,解决掉那些可有可无的依赖与耦合。另外由于Lambda是由事件驱动的,例如,被来自API网关的请求事情启动,被新存入S3存储对象的事件变化启动等。系统设计中必须能完全掌控这些事件的源头。

开发团队总结了采用Go与Lambda重构的成果:通过重构获得了性能提升、成本节约、增效降本。Lambda收到请求到应答的时间性能提高了70%,相当令人印象深刻的。更令人印象深刻的是运维成本的下降,重构的架构里删除了EC2(云服务器)、ELB(负载均衡)和RDS(云关系数据库),节省成本达到90%。团队研发效能上提高了30%,开发人员不再需要为服务器基础设施的修修补补写代码,更多精力用来创新,开发和扩展业务需求。

以上的Go语言结合serverless架构的案例是Capital One不断推进架构改进的其中一瞥。可以看出,身在金融行业的Capital One,很有些互联网企业的技术味道。正如Capital One所说到的,正是技术驱动给这家金融带给这家企业快速成长的重要源动力。

参考资料:

1. Capital One: Think More Like a Tech Company, Less Like a Bank. https://bankinnovation.net/uncategorized/capital-one-think-more-like-a-tech-company-less-like-a-bank/

2. Credit Offer APIs. https://www.capitalone.com/tech/solutions/credit-offers

3. A Serverless and Go Journey. https://www.capitalone.com/tech/cloud/a-serverless-and-go-journey

4. https://golang.google.cn/ref/mem

5. What are goroutines? And how do they actually work? https://medium.com/the-polyglot-programmer/what-are-goroutines-and-how-do-they-actually-work-f2a734f6f991

----- CTO视野原创 转载请注明出处 -----

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190823A0JO4W00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券