思考
在研发模式升级过程中,我们针对现有的导购业务进行了重构,可以说是使用了 Serverless 的方式进行了重写,而有一些老的应用,如果整体进行改造,这个成本会非常之大。
这个时候开发者就会有很常见的一个疑问:我原来的应用,怎么迁移到 Serverless 体系?
而我们的回答是两种:
使用 FaaS + Baas 的方式进行重构,代码更精简,就是需要改造成本
把整个传统应用作为一个函数,虽然不够优雅,但是能解决迁移的问题
把整个应用迁移到函数会有一些限制,会对代码结构和模型做一些微调,以符合整个 Serverless 的结构,毕竟新的体系和传统的代码模型是有所区别的。
阿里集团采用的是 FaaS + BaaS 的实现方式,而 FaaS 的整体概念和传统的应用不太一样。
在概念上,Serverless 比 FaaS 的外延要广,FaaS 属于 Serverless 的其中一种实现方式,主要解决的是用户自定义的代码逻辑如何做到 Serverless,也可以叫做 Serverless Compute,同时它也是事件驱动架构的一种。
而 CNCF Serverless 白皮书中也说到,Serverless Compute 是一种粒度更细的部署模型,通过一个或者多个 function,用于响应用户的需求。可以说,粒度小,灵活性高是它的最大特性。
在代码层面,为了让用户更好的理解,我们把传统代码的结构进行了分解,传统的 MVC 类型的代码,会分为几层。
HTTP 服务,原框架(koa/midway/egg…),Node.js 运行时,启动脚本等,将会变为函数运行时,固化下来
原有的 HTTP Router,Web 中间件等,将会由 HTTP 网关承接
原有的 Controller,业务逻辑(调用远程服务),继续保留,变为函数代码
原有的数据库,消息队列,RPC 调用等,都作为 BaaS 服务,用户只关心对应的服务,使用同一的 BaaS Client 进行调用
这样分解过后,我们对新旧两个体系的代码结构有了进一步认识,可以开始尝试修改部分代码,变成真正的 Serverless。
05 迁移
传统的应用,会暴露出一些对外的服务供外部调用,比如 HTTP,定时任务,RPC 服务等等,这些服务一般我们会单独抽离目录,并且和其他暴露的服务共享逻辑层代码,我们也经常称这些服务为“入口”。
在 Serverless(FaaS) 化的过程中,我们会根据当前部署平台的能力(比如阿里云 FC,腾讯 SCF 都会提供 HTTP 服务,定时任务,消息队列等等),将这些入口代码变为基于事件驱动的函数。
我们通过构建机制,在发布时生成不同的包,在共享一份逻辑代码的同时,部署到不同的环境,这个方案最大的优势是复用了原有的逻辑部分,可以和传统应用同步开发,而劣势也有,就是包依赖混在一起,由于函数对包大小有限制,可能会造成依赖过大等问题。
HTTP 相对于其他的来说会复杂很多,会有很多限制,这个我们在讲下游方案的时候再说。
针对上面的情况,对下游的数据调用我们也有相应的方案。我们将这些方案取了几个名字,比如代理模式和网关模式。
▐ 代理模式
首先来看看代理模式。一个传统的 Web 应用会分为 Router/Controller,以及逻辑层,在代理模式中,我们会保留传统的应用,只将原本的逻辑层部分迁移到了云函数中,暴露出 HTTP 服务。
这样的好处是代码变的精简,改动适中,也易于服务复用,缺点就是依旧会占用一个应用资源作为代理层。
而代理应用一般是通过 HTTP 客户端代理来实现的只是用户体感上需要做一些额外的支持,让开发者在体验上感觉到是调用了远端服务。
▐ 网关模式
第二种方式是网关模式,这个模式下,所有的代码都会迁移到新的体系,在 Web 层简单的时候比较适用。
该模式下,所有传统的 Web Router 会迁移到 HTTP Gateway 上,原本的路由,会话、鉴权等能力都将被网关所控制,而函数本身不需要关心这些,只需要关心数据即可。
业界现有的 FaaS 模型大多是这种结构,集团内也采用了这类结构去实践。
在这种模式下,原有的能力会碰到一些问题,举一些例子:
原有的 Web 中间件(koa middlware),会不知道如何处理,中间件大多是做请求流的拦截和消费,这个时候大多会拆成两部分,一部分被网关所处理,另一部分,只能交给函数本身,如果有共享的需求,也可以依赖模块来完成
原有的会话维持,一部分平台会进行透传 cookie,这个时候你依旧可以维持一个 sessionId,同时使用第三方来存储数据,但是如果网关不做这块,那么就很麻烦了
请求对象和原有的不同,由于函数获取的是 event,context 参数,或者原始的 request 对象,和现有的 koa 等框架不是很一致,上面的方法不一定有,会导致原有的代码做出修改和挑战
▐ 伪装者模式
那么有没有不修改代码的方案呢?我们尝试在函数外部进行代码包裹和数据模拟,让应用整个跑在函数之上,以一种 “微应用” 的方式继续存在。
我们把原有的 Web Server(midway/egg),启动起来,在运行时中通过一个固定的端口转发,把 FaaS 的请求参数包裹成 HTTP Request 对象,而在出口处,也将 HTTP Response 包裹为函数能读懂的形式,通过这样续命的方式来延续传统应用。而由于阿里云上的容器只读不能写,目前还无法直接用这种模式。
这种方式需要调整的是,框架需要使用单进程模型(机器配置,轻量化的要求),应用需要无状态(函数机制决定),以及没有长连接等高消耗的操作。
06 总结
关于 Serverless 的问题还有很多,本文也只是介绍了其中一部分内容,从阿里当前的状况讲起,分享了从去年到今年的研发模式升级实践,也介绍了在这其中我们的一些思考,传统应用迁移到 FaaS 体系下的方式。后续的整套方案也会在经过双十一的洗礼,大流量的考验后,开放给大家。
本文转载自淘系技术公众号。
原文链接:https://mp.weixin.qq.com/s/L7z0S5Oeg9Wtxqhh0c5AAw
评论