Serverless 域名管理方案
引言
Serverless应用一般都是微服务架构,项目会比较多,域名管理比较复杂。
本文提出了一种便捷的Serverless应用域名管理方案。
此方案基于 AWS 平台,使用 Serverless 框架及其周边生态实现。使用其它平台或框架的读者请酌情参考。
方案概述
- 前后端分离
- 每个前端项目占用一个独立的子域名
- foo 项目前端工程会使用 foo.demo.com
- bar 项目前端工程会使用 bar.demo.com
- 后端项目共用一个公共子域名,如 api。再通过子路径区分不同的业务(以及公共服务)。
- foo 项目后端工程会使用 api.demo.com/foo
- bar 项目后端工程会使用 api.demo.com/bar
- 将域名委托在对应的Serverless云服务商(如 AWS Route53),方便使用程序添加、删除记录。
- 使用工具进行域名管理。
示意图
1graph LR 2 3root(demo.com) 4foo-front(foo.demo.com) 5bar-front(bar.demo.com) 6 7subgraph backend 8api(api.demo.com) 9foo-backend(api.demo.com/foo) 10bar-backend(api.demo.com/bar) 11common-backend(api.demo.com/common) 12end 13 14root --> foo-front; 15root --> bar-front; 16 17root --> api; 18 19api --> foo-backend; 20api --> bar-backend; 21api --> common-backend;
实现方式
Serverless 中主要有两种方式管理域名,分别是基于 Serverless Components 的 Domain 和基于原生 Serverless 的 serverless-domain-manager。
它们的主要区别有两个:
- 应用领域不同,Serverless Components 和 原生 Serverless 的写法差异比较大。
- serverless-domain-manager支持子路径,而 Domain 暂时还不支持。
本方案中使用 serverless-domain-manager 管理后端域名,使多个工程即使不在同一个Git仓库中,也可以共用同一个域名(api.demo.com)。
至于前端项目域名就比较灵活了,具体看前端项目采用的是 Serverless Components 方式还是原生 Serverless 方式而定。
两种方式都需要先将域名的DNS服务改到Route53下,具体方法请参阅官方文档。
https://aws.amazon.com/cn/route53/
示例代码
基于serverless-domain-manager管理后端域名
基于serverless-domain-manager管理后端应用,共用同一个域名的示例:
- 创建serverless.yml,如下所示,将其中的 *.demo.com,foo 等换成对应的域名。
1service: 2 name: foo-backend 3 4custom: 5 serverless-offline: 6 port: 3000 7 domains: 8 prod: api.demo.com 9 staging: staging-api.demo.com 10 dev: dev-api.demo.com 11 12 customDomain: 13 domainName: ${self:custom.domains.${self:provider.environment.stage}} 14 basePath: 'foo' 15 stage: ${self:provider.environment.stage} 16 createRoute53Record: true 17 18# Add the serverless-webpack plugin 19plugins: 20 - serverless-domain-manager 21 22provider: 23 name: aws 24 runtime: nodejs12.x 25 stage: dev 26 apiGateway: 27 minimumCompressionSize: 1024 # Enable gzip compression for responses > 1 KB 28 memorySize: 256 29 environment: 30 stage: ${opt:stage, self:provider.stage} 31 AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1 32 33functions: 34 test: 35 handler: handler.test 36 events: 37 - http: 38 method: get 39 path: test 40 cors: true 41
-
安装相关依赖: serverless、serverless-domain-manager 等包
npm i -D serverless serverless-domain-manager
-
执行命令创建对应的域名
npx serverless create_domain --stage dev
这里的 dev 根据需要换成对应的 stage名。上面的 serverless.yml 中定义了三种stage(dev、staging、prod)分别对应三个不同的子域名。
如果此域名已经在别处创建过,此步骤可忽略
-
执行deploy
npx serverless deploy --stage dev
基于serverless-domain-manager管理前端域名
与上面的方案基本相同,去除 basePath: 'foo'
即可。
基于 Serverless Components Domain 管理前端域名
Serverless Components环环相扣,所以有可能您并不需要直接使用 Serverless Components Domain。
如果您在使用 Next.js 做前端应用,可考虑使用 serverless-nextjs-component。
serverless-nextjs-component的自定义域名使用极为简单:
-
创建 serverless.yml 文件,写入如下内容:
1# serverless.yml 2 3myNextApplication: 4 component: serverless-next.js 5 inputs: 6 domain: "example.com" # sub-domain defaults to www
-
运行 serverless ,自动执行部署及域名创建。(注意不是 serverless deploy)。
如果直接使用 serverless components domain,则可使用如下的 serverless.yml
1domain: 2 component: '@serverless/domain' 3 inputs: 4 privateZone: false 5 domain: mywebsite.com 6 subdomains: 7 www: ${websiteComponentInstance} 8 api: ${backendComponentInstance} 9 admin: ${anotherWebsiteComponentInstance}
HTTPS 证书
AWS Route53 会负责证书的自动创建和更新,如果是通过上述的两种serverless方案创建的域名,不需要关心证书问题。
总结
本文提出了一种简便的Serverless应用域名管理方案。
它将前端域名和后端域名独立开,规避了前端项目和后端项目处于同一子域名下带来的制约。
使得前端工程可以和后端工程互相独立。前端工程也可以不采用Serverless架构,直接做CNAME映射到其它静态托管服务,如 Github pages或netlify。