FreeWheel是美国传媒巨头康卡斯特(Comcast)集团旗下的高端视频广告技术供应商,90%以上的美国主流电视媒体和运营商都在使用FreeWheel的广告平台和技术。本文将带你了解名企FreeWheel核心业务系统研发团队将单体应用改造成云原生微服务应用的演进之路。
01
何为云原生应用
2010年,WSO2的创始人Paul Fremantle提出了云原生(Cloud native)一词。经历了10多年的发展和技术变革,云原生的定义和内涵都有了很大的变化。目前,云原生计算基金会(CNCF)对“云原生”的定义如下:
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。
该定义强调了应用要部署在以云为载体的动态环境中,即生而为云,同时列举了5种核心的云原生技术。基于此定义,我们可以认为:运行在云上(无论是哪种云)且使用了以上一种或多种技术构建的应用就是云原生应用。
这样的理解固然没错,但流于表象,我们希望能通过云原生技术的内在理念以获取更深层次的理解。
▊ 云原生应用是不断变化和演进的
从本质上讲,云平台提供的核心能力是复制(Replication),可以将各种类型的工作负载以手动或自动的方式进行复制和销毁,从而让应用具有弹性伸缩的能力。
因此,云上应用比传统应用更容易扩展,在规模和外部形态上是动态变化的(基于流量需求)。这是云原生应用之于传统应用比较大的区别。
我们再来看看云原生的代表技术——微服务。作为一种应用架构,它可以让每个服务独立开发、部署、运行。除去解耦的优点,这种构建方式可以让应用按需迭代,像细胞分裂再生一般不断更新,实现所谓的演进式设计。这一特性使得应用在内在的组织结构上也是动态变化的。而不可变基础设施(如容器、Pod)让这一变化方式更易实现。下图展示了一个微服务应用的各个组成部分都可以独立演进,且每一个服务自身也可以基于需要独立扩展。
因此,从技术特性的角度来看,云原生应用所具有的一大特点就是在外部形态和内部结构上都是动态变化的。
▊ 云原生应用以业务构建为核心
构建一个分布式系统通常要实现3部分内容:业务逻辑、控制逻辑、技术框架。
业务逻辑是重中之重,是为客户实现商业价值的核心所在,也是主要的开发活动。
控制逻辑用来辅助业务逻辑完成一些特定的需求,我们称之为非功能性需求,比如把数据切分成多段进行传输、用循环实现一个重试功能等,控制逻辑通常会利用中间件、类库的方式实现复用。
技术框架提供了封装好的模型、流程和工具库,提升了开发效率。当然框架并不是必须的,完全可以基于语言特性直接开发应用。
这3部分工作中其实只有业务逻辑是客户所要求的,即实现客户的商业价值。但因为应用在性能、可用性、可扩展性等一系列质量属性的需要,我们不得不开发一系列的和业务无关的非功能性需求,这些属于额外的工作,而且这些工作的开发时间占比很可能超过了业务本身。
我们再来看看云平台、云原生技术带来了什么。
从2006年AWS推出EC2到现在,云平台的职能发生了巨大的变化。一开始它只能提供单一的计算资源,应用开发的整个流程和依赖项依然需要开发人员实现和管理。
而现在,云平台的计算、存储、网络、安全等各种资源和能力面面俱到,大量的非功能性需求都下沉到了基础设施层面,比如通过服务网格轻松实现超时重试这样的流控能力。
下图展示了云平台的职能演进过程,越来越多的资源、特性、能力都可以通过云平台实现,开发者只需要管理好自己的数据,即业务本身。
因此我们认为,云原生应用应该是以业务构建为核心,利用云的能力获取、而不是自己开发非功能性需求,从而让开发过程变成纯粹而高效。
02
云上创新
应用构建需要遵循流程,应用演进亦是如此。亚马逊云科技提出的现代化应用构建(MAD)理论是开发云原生应用的实践方法,它将应用构建分为了3个阶段。
应用平移:将应用微服务并容器化,迁移上云;
云上重构:基于云的能力完成技术迭代,成本效益优化;
构建新应用:创建共享服务平台,开发速度优化。
FreeWheel正是这一方法的践行者,完成了从单体到微服务、迁移上云、云原生应用的改造实践。
▊ 应用平移
在应用平移阶段,我们主要做了两件事:首先是单体应用到微服务的改造,这个过程中我们用到了“绞杀者”模式;然后是容器化。
“绞杀”单体应用
FreeWheel早期的核心业务系统是基于Ruby构建的单体应用,运行了10年之久。随着业务特性不断的增加,应用变得庞大而臃肿,Ruby和JavaScript总代码行数超过了100万行,添加新功能和对既有功能的维护都变得举步维艰。
2017年团队着手对系统进行微服务改造,技术栈也随之迁移到以Golang为主的开发语言。为了快速上线新服务,尽快摆脱复杂单体在部署维护方面的痛点,我们使用了绞杀者模式进行迁移。
绞杀者模式(Stranger Pattern)是一种系统重构技术,它的名称来源于软件工程大师马丁福勒在澳大利亚雨林看到的一种叫绞杀无花果(Stranger fig)的植物。这种植物会缠绕在宿主树上吸收养料,然后慢慢向下生长,直到在土壤中生根,最终杀死宿主树使其成为一个空壳。在软件开发行业中这成为了一种重写系统的方式,即围绕旧系统逐步创建一个新系统,让它慢慢成长,直到旧系统被完全替代。
绞杀者模式的优势就在于它是一种渐进的过程,容许新旧系统共存,并给予新系统成长的时间。它的另一个优点是能够降低风险。一旦新系统无法工作你可以迅速的把流量切换回旧系统。
绞杀者应用的开发过程也有三个阶段:
转换:创建一个新应用
共存:逐渐从旧系统中剥离功能并由新应用实现,使用反向代理或其他路由技术将现有的请求重定向到新应用中。
删除:当流量被转移到新应用后,逐步删除旧系统的功能模块,或者不在维护。
下图展示了这一过程。
我们对旧系统的改造工作包括前端和后端两部分,后端部分是把原来的业务逻辑逐一拆解成微服务;前端部分是把原来的Rails应用重构为基于React的UI界面并调用微服务提供的新接口。
应用容器化
在完成应用微服务改造的同时,另一件上云的准备工作就是应用容器化。微服务让应用具有了按需演进的能力,容器这种能力变得更易实现。
一方面,容器容许我们使用更小的计算单元,降低构建成本;另一方面,容器对齐了应用的构建标准,让不同团队、基于不同技术栈的服务以统一的方式部署运行,简化了对基础设施的维护,并让CICD流水线的构建变得统一和便捷。
根据CNCF 2020年的问卷调查显示,超过90%的组织和团队都已经使用容器进行应用的构建和部署。应用程序容器化已经成为业界标准。
▊ 云上重构
容器化仅仅是基础,应用还需要通过编排实现生命周期管理。团队选择了AWS托管的Kubernetes产品EKS作为容器编排和管理平台。到目前为止,我们已经创建了16个集群,总Pod数量超过5000个。
一般来说,将应用从容器转变为以Kubernetes Pod为载体的过程主要要做两件事。
首先针对应用特性选择对应的资源类型,比如最常用的无状态服务使用Deployment,有状态服务选择StatefulSet,守护进程选择DaemonSet,任务相关的选择Job、CronJob。然后将服务暴露出去使得集群内或者集群外能够访问。
进入应用的外部流量有两种:一种是页面访问,另一种是OpenAPI。
为了控制外部流量我们使用API Gateway作为入口网关,除基本的路由外,还实现了鉴权和限流等功能。
内部流量也有两种:一种来自集群外部,其他存量系统对应用的访问,我们会使用ExternalName与Route53 DNS域名绑定来实现;另外一种就是微服务之间的调用,可以直接通过服务名方式访问。
随着微服务的不断增多,服务之间的调用拓扑也越加复杂,流量控制、治理和监控等需求也越来越重要。
在经过调研和探索之后,我们在应用中引入了Istio Service Mesh管理服务间的流量。通过它我们实现了按类型的流量切分,将来自页面和API的请求分发到不同的Endpoint去处理;而超时、重试、熔断这些弹性能力也可以通过声明式配置实现,无须手动编写控制逻辑。
在存储层面上,我们也做了重构,基于数据特性选择最合适的解决方案。比如把广告库存信息这样的元数据迁移到了NoSQL键值数据库,以提升其查询效率。
另一方面,与监控平台的整合让微服务应用的可观察性获得极大提升。应用的业务日志和请求日志都会存储在ELK中,流量指标也统一收集到监控平台的Prometheus系统,并通过Grafana Dashboard展示。我们还基于Jaeger构建了一个分布式追踪系统,可以方便地查看服务的调用链路并进行根因分析。
下图展示了CNCF定义的云原生核心技术。至此,云原生应用形态逐渐清晰。从微服务架构、容器化,到Kubernetes容器编排,再到使用Service Mesh实现流量控制,应用已经使用了所有云原生定义中的核心技术。
▊ 构建新应用
在应用架构不断完善的同时,我们还积极探索更加灵活和轻量级的Serverless解决方案,通过AWS Lambda实现了特定场景的业务需求。
这些业务场景通常都有一个共性:一般是异步的、计算型的任务,不需要实时在线。
为这种业务构建一个微服务显然不合理(异步、离线计算任务不需要实时在线,运行完即结束,一个总是在线的守护进程服务空闲时间太多,浪费资源)。而Serverless按需启动、根据流量自动伸缩的能力非常适合这些场景。经过对比测试,我们发现资源成本降低了很多。同时,因为不需要对服务器等基础设施进行管理,运维效率也提高了。
除了依赖现有的开源和托管产品构建应用,团队还开发了一系列的自研平台,覆盖应用的构建、运维、监控等方面,可以让工程师以所及即所得的方式实现应用程序的全生命周期管理。
例如我们开发了一个内部代号为Bingo的低代码开发平台(LCDP),可以以可视化方式构建出一个Serverless或微服务的代码框架,并自动生成CI/CD流水线。开发人员只需要实现具体业务逻辑即可,极大地减少了框架层面的重复性劳动,提升了开发效率。公司的运维团队还开发了一个强大的运维平台 FreeWheel Operation Center(FOC),可以与Kubernetes集群深度对接,完成集群的监控、部署、更新等运维工作,降低了手动运维出错概率,提高了运维效率和安全性。
下图展示了目前核心业务系统的架构形态,准确来说我们的应用已经发展成为一个微服务加无服务器的混合云原生架构,并通过Kubernetes和Istio完成应用编排管理和服务治理工作。
03
未来期许
如果说使用了云原生技术是构建云原生应用的第一阶段,那么下一个阶段就是以原生的方式开发应用,即在设计思路上优先基于云原生技术和编程范式进行应用的构建。
比如,利用Kubernetes控制器模式以声明式配置的方式管理应用资源;优先选择服务网格的能力实现服务治理而不是手动开发控制逻辑;通过服务的可观察性以开发者视角主动关注应用的运行状态。
上述这些都需要开发人员摈弃传统开发习惯,以云原生的理念设计和方法来构建应用。也只有这样,才能实现云原生技术以业务为核心的愿景,回归软件开发的本源。
《云原生应用架构:微服务开发最佳实战》一书从真实案例出发反推技术难点,汇聚名企一线工程师的真知灼见!
一网打尽微服务、云原生、服务网格、敏捷开发、分布式事务、无服务器架构、可观察性、质量保证、CI/CD等前沿话题,热点技能各个击破!
要想了解更多有关名企云原生微服务最佳实战的相关话题,就来读一读《云原生应用架构:微服务开发最佳实战》吧!
FreeWheel成立于2007年,是美国传媒巨头康卡斯特集团旗下的高端视频广告技术供应商,在北京、纽约、旧金山、芝加哥、伦敦、巴黎等地设有分支机构。FreeWheel核心业务系统开发团队在多年的实践中探索出了一条云原生微服务应用构建之路。
本书基于这些实践经验,从设计、开发到测试、部署,介绍了团队如何利用云原生技术为应用开发的全生命周期赋能。从架构技术选型到具体工程实践,书中内容理论联系实际,较为全面地剖析了容器落地、服务网格、无服务器计算、持续集成和持续部署等核心云原生技术,适合关注微服务、云原生技术的架构师、工程师及技术决策者阅读。
京东满100减50,扫码即购!