本次改造的项目题材取自GiiBee CMS
Serverless架构改造的仓库地址
1. 题材选择
最初的动机是想针对传统的项目做一个完整的Serverless架构重构,并且想找一些有一定复杂度能够展示Serverless架构分布式特色的项目,GiiBee CMS的项目结构比较符合预期。整个项目采用的技术栈是前端js全栈,Api服务使用了 NestJS, 管理后台是标准的 Vue + Element UI 的单页面应用形式,展示首页则是用了Nuxtjs这个既可作 SSR 也可作SSG 的前端渲染框架,三个部分各自独立又有联系,整体看是一个项目,非常契合Serverless架构的分布式结构。
2. 架构设计
这套CMS系统的三个部分在部署部分是独立的,但在访问侧却应该是统一的,首页,后台管理,OpenApi 服务需要共用同一个域名,这个时候需要有个前置网关入口来做相应的分流处理。这里提供两套方案,一套是以阿里云ApiGateway为入口流量处理的方案,另外一个则是以阿里云DCDN边缘应用程序为入口流量处理的方案,两个方案都有各自的优劣,后面会详细展开。并且为了能够将项目的完整功能呈现出来,首页的渲染方式准备使用SSR,整个的架构设计方案如下。
方案一:ApiGateway
方案二:DCDN边缘应用程序
3. 工程改造
对整个工程源码进行解读后,将需要改造的部分进行如下罗列:
3.1 前端静态资源
主要包括网站首页图片,产品图片等,原项目中静态资源存放在server/public/uploads 目录下,跟服务端的耦合度比较高,而服务端最终需要运行到函数计算FAAS服务中,无写权限,这部分需要做一些处理。有两种方案可以参考:
- 将目录映射到Nas上,利用Nas进行读写,这种改造成本较低,不过缺点是依然依赖主业务服务。
- 单独将静态资源文件存储到 OSS,实现跟业务服务的解耦,缺点就是改造成本比第一个方案要高。
3.2 日志
后端服务的日志写入同样会受限,与静态资源不同的是日志服务可以单独写到专业的日志存储服务上不如SLS。
3.3 数据库
数据库部分也要单独准备可访问的链接地址,账号,密码等,这些同样需要改动源码。
3.4 配置项
比如上面提到的数据库信息,日志地址信息,静态资源地址信息等,这些配置项在Serverless架构模式下都需要单独抽离出来,以环境变量的方式替换存在于源码中的位置,以便安全和灵活的设置。
3.5 其他
除了上面几个基本项外,剩下的就是根据业务功能做适当的调整了,实践中比如路径的改动,功能性增加等。此外部署配置部分的内容也需要在源代码中体现,比如使用函数计算Customer Runtime 部署后端Api服务,就需要准备好bootstrap入口文件。
3.6 部署方案
其实就是如何配置ServerlessDevs s.yaml, 我们需要先配置 Api服务的配置项,将Nestjs的后端项目部署到函数计算,将后端管理系统的前端静态资源上传到OSS对象存储,将主站内容做SSR的构建,然后同样以部署函数的方式部署到函数计算上,最后还要配置网关及路由关系映射,增加DNS解析等。理想的状态是,所有这些操作都可以用统一工程化的方式一键处理,具体实施的环节我将在后面的文章中做详细介绍。
s.yaml的基本信息展示如下:
edition1.0.0 name modern-app-new access hanxie vars region cn-hangzhou fc serviceName'modern-app-new' functionName'modern-app-new' triggers'modern-web-api' staticPath'/mnt/auto/modern-app-new/public' logPath'/mnt/auto/modern-app-new/logs/application.log' oss bucketName'hanxie-modernweb-registery' bucketObject'admin' bucketObject2'portal' services www-admin# 静态资源 component oss props region $ vars.region bucket $ vars.oss.bucketName # OSS bucket 自动生成 subDir $ vars.oss.bucketObject acl public-read # 读写权限 codeUri ./admin/dist # 指定本地要上传目录文件地址 website# OSS 静态网站配置 index index.html # 默认首页 error 404.html # 默认 404 页 subDirType redirect # 子目录首页 404 规则 # customDomains: # OSS 绑定域名 # - domainName: auto # protocol: HTTP api-server component fc actions post-deploy# 在deploy之后运行 plugin keep-warm-fc args url http //modern-app-new.modern-app-new.1611387345152601.cn-hangzhou.fc.devsapp.net # actions: # post-deploy: # - component: fc nas upload -r ./server/logs /mnt/auto/modern-app-new # - component: fc nas upload -r ./server/public /mnt/auto/modern-app-new props region $ vars.region service name $ vars.fc.serviceName description Aliyun RAM Role internetAccesstrue nasConfig auto function name $ vars.fc.functionName description Native recording handler timeout3000 memorySize1024 runtime custom environmentVariables NODE_ENV production dbHost dbPort3306 dbPassword dbUserName staticPath $ vars.fc.staticPath logPath $ vars.fc.logPath codeUri ./server caPort3000 triggers name $ vars.fc.triggers type http config authType anonymous methods GET POST PUT DELETE HEAD OPTIONS customDomains domainName auto protocol HTTP routeConfigs path /* serviceName $ vars.fc.serviceName functionName $ vars.fc.functionName ssr-portal component fc actions post-deploy# 在deploy之后运行 plugin keep-warm-fc args url http //modern-app-portal.modern-app-portal.1611387345152601.cn-hangzhou.fc.devsapp.net # actions: # post-deploy: # - component: fc nas upload -r ./server/logs /mnt/auto/modern-app-new # - component: fc nas upload -r ./server/public /mnt/auto/modern-app-new props region $ vars.region service name modern-app-portal description Aliyun RAM Role internetAccesstrue nasConfig auto function name modern-app-portal description Native recording handler timeout3000 memorySize1024 runtime custom codeUri ./web caPort3001 triggers name modern-app-portal type http config authType anonymous methods GET POST PUT DELETE HEAD OPTIONS customDomains domainName auto protocol HTTP routeConfigs path /* serviceName modern-app-portal functionName modern-app-portal
4. 总结
上面介绍了对传统前端应用做Serverless架构重构的基本思路,从设计到工程改造到部署方案都有涉及,单单是内容的罗列就有很多内容,真实的改造中遇到的问题更多,也曾一度有打退堂鼓的想法,怀疑过Serverless改造的投入产出是否合理,但当真正完成后又会有非常大的成就感,在后续对项目的逐渐完善中进一步体会到Serverless架构的魅力所在,相信各位小伙伴在跟随笔者完成这个Serverless架构改造系列文章后也会有相同的感觉,接下来我们一起探索!