中年|Serverless 实战:通过 Component 实现多地域部署容灾
【中年|Serverless 实战:通过 Component 实现多地域部署容灾】
作者 | 刘宇
策划 | 田晓旭
单点故障是实际生产中无法避免的 , 单副本的存储方案也早已无法满足业务的可靠性要求 。 现在 , 我们通常都会做双机存储架构 , 会涉及到主备、主从、主主模式 。
本文插图
在 Serverless 架构下 , 高可用方案或者容灾方案是否还需要主备、主从以及主主等模式?如果还需要 , 那么又是什么样子?
1 Serverless 与多地域部署
针对服务可用性 , 几乎每个云厂商都会有非常高的承诺 , 但是我们也不能掉以轻心 , 认为不会出现故障导致不可用 , 容灾方案是必须要有的 。
在传统主机时代有主备、主从以及主主模式 , 这个模式更多针对的是单台机器或者某个集群 。 但是在 Serverless 架构下 , 没有机器和集群的概念(至少在用户层面没有) , 是不是就表示在 Serverless 架构下无法做容灾?
理论上 , 云厂商会保证整个服务的可用性 , 如果云厂商管理的某个机器出现故障 , 机器会被及时剔除 , 确保新的函数在安全、稳定、健康的环境下启动 , 正常提供服务 。 但在实际情况中 , 由于某些原因 , 云厂商也可能会在某个地域出现大规模故障 , 这时如何确保服务依旧可用 , 而不是苦苦等待云厂商的恢复?
针对单地域解析的网站 , 我们可以实现多地域的主备方案 。 在云函数中 , 多地域的主备方案更加经济实惠 , 因为函数是按量付费的 , 完全可以将函数复制到其他的地域 , 只要不进行触发 , 就不会产生额外的费用 。 相对于传统主机时代的主备模式 , 这种主备方案显得更加人性化 。
一般情况下 , 单地域部署的服务中比较容易出问题的是 API 网关服务、云函数服务、数据库服务 。 其中 , 数据库服务可以考虑跨地域主从、跨区域同步 , 一旦出现问题 , 就在函数中做一个负载 , 确保整体数据不会出现问题 , 在腾讯云的云数据库描述下可以看到:
本地 IDC 机房 MySQL 数据库与云数据库 MySQL 之间可以通过数据迁移服务实时同步数据 , 本地 IDC 机房如遇到断电、网络故障等引起数据库服务中断 , 可迅速切换数据库服务至作为灾难备份的云数据库 MySQL 实例 , 实现数据库容灾;同时 , 云数据库 MySQL 可支持同城多可用区灾备 / 跨城灾备 , 保障高可用 。所以说 , 数据库相关服务的容灾可以通过备用数据库来提高可用性 。
那么云函数和 API 网关怎么解决?
以多地域部署容灾为例 , 我们可以考虑这样的架构:
本文插图
同样是作为单地域解析服务 , 相对来说 , 多地域部署更加安全稳定 , 一旦某个地域的服务出现问题(例如 API 网关 , 云函数) , 都可以通过监控程序及时发现 , 并且迅速切换解析到其它地域 。 多地域部署的监控函数与时间触发器进行结合 , 定期进行网站可用性的排查 , 一旦出现问题 , 就可以在云解析层面进行解析切换 , 实现单地域服务的多地域部署容灾方案:
本文插图
这个方案的逻辑是先请求服务是否可用 , 如果不可用 , 则获取容灾列表 , 剔除不可用的服务 , 并通过云解析进行可用区的解析 。 在实际生产中 , 一旦确定某个服务不可用 , 还要进行精确告警 , 在获得到不可用解析记录对应的服务之后 , 通过邮件或者企业微信、短信等方法进行告警 。
至此 , 一个简单版的“高可用”服务就算做好了 , 有的读者可能有所疑问:
对服务进行修复 , 是否比切换解析更加靠谱呢?
针对问题 1 , 其实切换解析是需要时间的 , 虽然一小部分的机房可能不会按照设定的 TTL 进行生效 , 但是大部分的机房都是可以按照设定及时生效 , 所以需要注意的是 , 在添加解析的时候要尽可能地确保 TTL 时间短一些 , 目前腾讯云的云解析付费版最低 TTL 可以设置为 1s , 免费版是 600s 。
针对问题 2 , 在云函数上运行服务很少会因为流量太高导致服务不可用 , 或者服务中存在 bug 导致整个项目不可用 , 因为云厂商会解决很大一部分的可用性 , 例如流量并发问题等 。 另外 , 就算是程序中存在 bug , 在 Serverless 架构下 , 函数的前一次后一次运行实际上关联性不大 , 所以完全可以通过告警来确定 , 人为排查消灭隐患 。 事实上 , 在 Serverless 架构下出现大规模服务性灾难 , 多数情况都是云厂商的问题(此处已经排除掉用户代码层面的 bug) , 而这种问题一旦出现 , 就不是我们能够掌控的了 , 是否可以修复、什么时候修复 。
本文插图
如果是 API 网关层面出现问题 , 可以通过上一层来解决 , 例如云解析的切换;如果是函数层面出现问题 , 可以考虑切换到 API 网关到同区域的备用函数;如果是函数服务的整个区域性故障(概率非常低) , 可以考虑切换解析到备用区 。
如果不是单地域提供服务 , 那么就需要考虑多地域部署、多地域就近接入以及多地域容灾方案 。
本文插图
从上图可以看到 , 我们将一个域名 , 划分地域进行解析 , 例如华北、华东两个地区 , 就可分别解析到北京 1 区、北京 2 区两个不同的机房中两台不同的服务器上 。 当其中一个服务不可用时 , 其他区域不受影响 , 可以使用云函数对解析进行修改 , 将其解析到每个地区的备用服务上 。
本文插图
整体结构图:
本文插图
传统的服务需要每个地区部署多套服务 , 无疑大大增加了成本 , 但是在 Serverless 架构下 , 即使部署了多套云函数还是按量付费 , 大大节约了成本 。
若采用 Serverless 架构作为后端服务 , 以华北地区为例 , 华北地区用户在访问后端服务的时候 , 通过 DNS 重定向到北京区的 API 网关 , 然后再由 API 网关触发北京区云函数 , 此时我们需要两个云函数对服务进行监控 , 一个函数对云函数进行监控 , 当云函数服务失效之后 , 可以将 API 网关绑定到备用的函数上 , 另一个监控是对 API 网关进行监控 , 当某个地域的 API 网关失效之后 , 可以对解析进行修改 , 重定向到备用地域的 API 网关上 , 尽可能快速的保证服务的可用性 。
如果想要让服务更稳定 , 可以增加数据库 / 对象存储的主备与监控 , 以及数据库 / 对象存储封装函数的主备与监控 , 这样就可以在四个层次做监控告警以及服务保障:在我们的服务中 , 通常数据库或者存储模块不会同时在多个区域部署 , 也可能只有一套主备服务 , 此时 , 可以通过对数据库和对象存储做一层封装 , 即在外层增加一个对应的函数 , 通过内网对数据库以及对象存储进行数据转发等 , 通过外部云函数调用 invoke(专线调用)大幅度降低由于网络原因造成的延时 , 当云数据库 / 对象存储出现问题 , 在接入层(数据库 / 对象存储封装函数)一侧 , 进行切换 , 将云数据库 / 对象存储切换到备用服务上 , 并进行告警;当接入层发生故障 , 无法继续服务时 , 在逻辑函数初(北京区 / 上海区 / 广州区) , 切换封装函数 , 即通过内部专线(函数间调用)调用备用接入层函数;同理 , 当逻辑函数 / 业务函数出现故障 , 监控脚本对 API 网关侧的后端服务进行切换 , 切换到备用逻辑函数 / 业务函数上;如果当 API 网关出现故障 , 无法继续提供服务 , 则只能在解析层面做切换 。 在整个这样的一个流程中 , 每一阶段或者说每一层面都有自身的负载机制 , 主备策略 , 可以根据不同组件出现故障的实际情况 , 进行多层级的自动切换 , 进而保证业务可用时长的一个最大化 。
此处 , 有读者可能有疑问:为什么某个函数会无法提供服务?底层服务的容灾机制 , 不是云厂商要提供的么?理论上 , 这个容灾机制是云厂商提供的 , 并且函数是无状态的 , 只要确保业务逻辑无问题 , 是不需要进行某些层级的主备容灾等 。 但是实际上 , 各个云厂商均没有办法保证某个服务 100% 可用 。 例如 2019 年 6 月 2 日凌晨 2 点 , 亚马逊云 AWS 突发受大规模故障 , 直到当天下午 1 点 48 分故障解除 , 故障时间将近 12 小时 。 所以 , 虽然云厂商会提供相对安全与可靠的容灾机制和服务 , 但还是很有必要在自身层面额外处理一下 , 尽可能保证服务安全与稳定 。
2 通过 Serverless Framework 进行多地域部署与解析
函数的多地域部署
以腾讯云为例 , 基础的 Component 跨地域部署不是很容易实现 。 虽然修改区域将函数部署到多个地域是可以实现的 , 但实际部署时每个区域的函数还会有一些额外的配置 , 所以这个时候可以借助多地域部署的组件来实现:tencent-scf-multi-region
相对于传统的tencent-scf
组件而言 , 这个组件的 yaml 将region
字段变成了兼容list
形式 , 同时增加了子地域的额外配置 , 例如 yaml:
hello_world:
component: "@serverless/tencent-scf-multi-region"
inputs:
codeUri: ./
description: This is a template function
region:
-ap-guangzhou
- ap-shanghai
environment:
variables:
ENV_FIRST: env1
ENV_SECOND: env2
handler: index.main_handler
memorySize: 128
name: hello_world
runtime: Python3.6
timeout: 3
events:
- apigw:
name: serverless_test
parameters:
protocols:
- http
description: the serverless service
environment: release
endpoints:
- path: /users
method: POST
- path: /usersss
method: POST
ap-guangzhou:
environment:
variables:
ENV_FIRST: env2
ap-shanghai:
events:
- apigw:
name: serverless_test
parameters:
protocols:
- http
description: the serverless service
environment: release
endpoints:
- path: /usersd
method: POST
测试部署效果:
$ sls --debug
DEBUG ─ Resolving the template"s static variables.
DEBUG ─ Collecting components from the template.
DEBUG ─ Downloading any NPM components found in the template.
DEBUG ─ Analyzing the template"s components dependencies.
DEBUG ─ Creating the template"s components graph.
DEBUG ─ Syncing template state.
DEBUG ─ Executing the template"s components graph.
DEBUG ─ Compressing function hello_world file to /Users/dfounderliu/Desktop/ServerlessComponents/test/scf_test/.serverless/hello_world.zip.
DEBUG ─ Compressed function hello_world file successful
DEBUG ─ Uploading service package to cos[sls-cloudfunction-ap-guangzhou-code]. sls-cloudfunction-default-hello_world-1583816589.zip
DEBUG ─ Uploaded package successful /Users/dfounderliu/Desktop/ServerlessComponents/test/scf_test/.serverless/hello_world.zip
DEBUG ─ Creating function hello_world
DEBUG ─ Updating code...
DEBUG ─ Updating configure...
DEBUG ─ Created function hello_world successful
DEBUG ─ Setting tags for function hello_world
DEBUG ─ Creating trigger for function hello_world
DEBUG ─ Starting API-Gateway deployment with name hello_world.ap-guangzhou-hello_world.serverless_test in the ap-guangzhou region
DEBUG ─ Service with ID service-p14470dc created.
DEBUG ─ API with id api-pg3ihnoi created.
DEBUG ─ Deploying service with id service-p14470dc.
DEBUG ─ Deployment successful for the api named hello_world.ap-guangzhou-hello_world.serverless_test in the ap-guangzhou region.
DEBUG ─ API with id api-op4jqvba created.
DEBUG ─ Deploying service with id service-p14470dc.
DEBUG ─ Deployment successful for the api named hello_world.ap-guangzhou-hello_world.serverless_test in the ap-guangzhou region.
DEBUG ─ Deployed function hello_world successful
DEBUG ─ Compressing function hello_world file to /Users/dfounderliu/Desktop/ServerlessComponents/test/scf_test/.serverless/hello_world.zip.
DEBUG ─ Compressed function hello_world file successful
DEBUG ─ Uploaded package successful /Users/dfounderliu/Desktop/ServerlessComponents/test/scf_test/.serverless/hello_world.zip
DEBUG ─ Creating function hello_world
DEBUG ─ Updating code...
DEBUG ─ Updating configure...
DEBUG ─ Created function hello_world successful
DEBUG ─ Setting tags for function hello_world
DEBUG ─ Creating trigger for function hello_world
DEBUG ─ Starting API-Gateway deployment with name hello_world.ap-shanghai-hello_world.serverless_test in the ap-shanghai region
DEBUG ─ Service with ID service-7daktopz created.
DEBUG ─ API with id api-4v40ce4u created.
DEBUG ─ Deploying service with id service-7daktopz.
DEBUG ─ Deployment successful for the api named hello_world.ap-shanghai-hello_world.serverless_test in the ap-shanghai region.
DEBUG ─ API with id api-emkl7ov4 created.
DEBUG ─ Deploying service with id service-7daktopz.
DEBUG ─ Deployment successful for the api named hello_world.ap-shanghai-hello_world.serverless_test in the ap-shanghai region.
DEBUG ─ Starting API-Gateway deployment with name hello_world.ap-shanghai-hello_world.serverless_test in the ap-shanghai region
DEBUG ─ Using last time deploy service id service-7daktopz
DEBUG ─ Updating service with serviceId service-7daktopz.
DEBUG ─ API with id api-2zag45hq created.
DEBUG ─ Deploying service with id service-7daktopz.
DEBUG ─ Deployment successful for the api named hello_world.ap-shanghai-hello_world.serverless_test in the ap-shanghai region.
DEBUG ─ Deployed function hello_world successful
hello_world:
ap-guangzhou:
Name: hello_world
Runtime: Python3.6
Handler: index.main_handler
MemorySize: 128
Timeout: 3
Region: ap-guangzhou
Namespace: default
Description: This is a template function
APIGateway:
- serverless_test - POST - http://service-p14470dc-1256773370.gz.apigw.tencentcs.com/release/users
- serverless_test - POST - http://service-p14470dc-1256773370.gz.apigw.tencentcs.com/release/usersss
ap-shanghai:
Name: hello_world
Runtime: Python3.6
Handler: index.main_handler
MemorySize: 128
Timeout: 3
Region: ap-shanghai
Namespace: default
Description: This is a template function
APIGateway:
- serverless_test - POST - http://service-7daktopz-1256773370.sh.apigw.tencentcs.com/release/users
- serverless_test - POST - http://service-7daktopz-1256773370.sh.apigw.tencentcs.com/release/usersss
- serverless_test - POST - http://service-7daktopz-1256773370.sh.apigw.tencentcs.com/release/usersd
35s hello_world done
通过以上部署 , 就可以成功将函数部署到不同的地域 , 并且针对不同地域进行额外的配置 。
上层服务的多地域部署与解析
就目前来看 , tencent-scf更多是一个基础组件 , 更多人则是在使用 Koa、Express 等组件 , 那么对于这种相对高阶的组件 , 是否可以多地域部署呢?从目前文档的描述来看是可以进行多地域部署 , 且可以进行自动解析 , 以tencent-tornado为例:
TornadoTest:
component: "@serverless/tencent-tornado"
inputs:
region:
- ap-guangzhou
- ap-shanghai
functionName: tornadoFunctionTest
tornadoProjectName: app
code: ./
functionConf:
timeout: 10
memorySize: 256
environment:
variables:
TEST: vale
vpcConfig:
subnetId: ""
vpcId: ""
apigatewayConf:
protocols:
- http
environment: release
customDomain:
- domain: anycodestest1.com
isDefaultMapping: "FALSE"
pathMappingSet:
- path: /
environment: release
protocols:
- http
- domain: anycodestest2.com
isDefaultMapping: "FALSE"
pathMappingSet:
- path: /
environment: release
protocols:
- http
cloudDNSConf:
ttl: 603
status: enable
ap-guangzhou:
functionConf:
timeout: 20
apigatewayConf:
protocols:
- https
cloudDNSConf:
recordLine:
- 电信
- 联通
部署结果:
TornadoTest:
functionName: tornadoFunctionTest
ap-shanghai:
apiGatewayServiceId: service-mdnjhsp3
url: http://service-mdnjhsp3-1256773370.sh.apigw.tencentcs.com/release/
ap-guangzhou:
apiGatewayServiceId: service-nh6xgutk
url: https://service-nh6xgutk-1256773370.gz.apigw.tencentcs.com/release/
DNS: Please set your domain DNS: f1g1ns1.dnspod.net | f1g1ns1.dnspod.net
通过这样一个组件 , 就可以完成框架的跨地域部署与解析 。
3 总 结
至此 , 我们基本完成了一个基于 Serverless 的高可用框架的案例探讨 , 从对单解析的分析 , 到对多解析的策略制定 , 再到最后基于 Serverless 架构的高可用模型 , 虽然文中案例仅仅可以作为学习参考使用 , 在实际生产中会面临很多难题 , 有些地方还需要针对实际项目做一些特殊的修改和修正 , 但是这样一个简单的基于 Serverless 架构的高可用模型 , 基本上可以发挥出 Serverless 架构的特点 , 包括 Serverless 架构的按量付费功能 , 在不使用的时候则不需要收费 , 在部署多套云函数的时候不会因为部署量增加而产生额外的费用;在这个项目中 , 包括 API 网关等触发器对函数进行触发 , 也会包括函数间的编排和调用 , 更有 FaaS 与 BaaS 紧密结合 , 通过专线跨地域 Invoke , 在外层还会增加多套监控告警函数以及 DNS 切换函数、云函数切换函数等尽可能保证服务的稳定与可用性;为了更加简单的进行多地域部署 , 还通过了 Serverless Framework 实现了多地域部署方案 。
在实际生产生活中 , 无论是单地域服务还是多地域就近接入服务 , 多地域部署容灾都是很重要的 , 尤其在 Serverless 架构下 , 按量付费让主备模式成本骤降 , 100% 可用性几乎是一个不可能事件 , 但我们可以共同探讨相对优秀的高可用方案 。
【来源:InfoQ】
声明:转载此文是出于传递更多信息之目的 。 若有来源标注错误或侵犯了您的合法权益 , 请作者持权属证明与本网联系 , 我们将及时更正、删除 , 谢谢 。邮箱地址:newmedia@xxcb.cn
推荐阅读
- 成龙的功夫是杂技,洪金宝胖的不灵活,周比利评价两人实战能力
- 减肥|JAMA:减肥要趁早,25岁就该开始预防中年期肥胖
- 人到中年,常吃3种食物,健脑益智,美白抗衰,保护心血管
- IPFS/Filecoin上线后会涨的八大理由,实战讲解!
- 中年|《中国新说唱2020》全民搞哈开团日
- 中年|点燃创新之火,合力解除“缺芯”之痛
- 中年|画像“标签”生产实操指南(二)之产出清晰的标签数据需求
- 中年|从原型模式到浅拷贝和深拷贝
- 中年|宁愿2450亿打水漂,也不使用华为设备?如今却沦为“国际笑话”
- 中年|Angular export class AppComponent里定义变量的实现原理