learn-tech/专栏/Serverless进阶实战课/18实战指南:Serverless沙场老兵的一线使用经验.md
2024-10-16 06:37:41 +08:00

226 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

因收到Google相关通知网站将会择期关闭。相关通知内容
18 实战指南Serverless沙场老兵的一线使用经验
你好,我是静远。
恭喜你完成了Serverless核心技术和扩展能力的学习从这节课开始我们就要运用之前所学的知识点开始实战演练了。
前面我们讲到的触发器、冷启动、扩缩容、运行时、可观测等知识点相信你都已经掌握得差不多了随便拿出一个相关的问题你也可以快速应对。但是这些零碎的“武功招式”怎么才能在实战中运用起来呢Serverless架构模式的开发和传统架构应用的开发如此不同我们需要格外注意哪些“坑”呢
今天我就把平常“取经”得到的经验以及自己总结出来的“客户常见难题”分成方案设计、资源评估、调用速度、开发技巧、线上运维等几个方面跟你聊聊如何用好“Serverless”。
希望这节课让你能够在选择合适的方案和开发手段这些方面得到启发真正享受Serverless带来的红利。
方案选型
方案选型的时候选错场景和技术大方向是比较忌讳的不仅可能导致服务不稳定还会导致修补工作量上升。那么什么情况下适合用Serverless技术呢
比较适合Serverless技术的场景通常由数据处理计算、应用后端服务、事件触发处理、有状态服务和传统服务升级 5个维度组成。
接下来我们可以对每一个业务的特性做一个抽象总结看看5个维度不同的侧重点让你在日新月异的Serverless场景迭代下也能够自己动手丰富这张技术选型图谱。
数据处理计算的场景
如果是大流量数据且没有峰谷显著特性的话你完全可以使用Spark、Flink这样的技术来处理只有在峰谷显著的时候Serverless的“极致弹性”才有发挥的余地。也就是数据场景流量变化较大、需要算力动态调配的时候选用Serverless。
事件触发类场景
这个场景是从FaaS诞生就常用的领域了。它的特性在于“流量的不稳定”有就触发没有就缩容至0。如果你的业务场景比较轻量且流量不稳定那么“精益成本”按需使用按量付费的Serverless就是你的最佳选择。
应用后端服务
区别于传统的微服务应用应用后端服务更多的是对于微服务的一种补充多用于相对独立、架构简单的业务应用。比如小程序、H5活动页、BFF的场景它印证了Serverless“快速交付”这一特点。
这三个场景我用蓝色做了区分不管是通过函数编写还是自定义镜像FaaS形态的技术都足以支撑了。而黄色的部分代表Serverless内涵延伸后尤其是近几年技术底座和产品发展后能够支撑更多的场景。我们继续往下说。
有状态的场景
有状态的场景打破了之前狭义上Serverless无状态的特性让长进程、多任务、有状态需求的交互也能在Serverless下完成。
传统服务升级
当我们遇到历史包袱比较重比如服务架构集成了SpringBoot、SpringCloud、Dubbo等框架的情况就可以考虑通过Serverless托管服务的模式转型了。另外如果希望省去K8s的运维和容量的规划成本考虑Serverless的容器转型也可以划分在这类场景中。
除去这张图上的5个维度反过来想一想哪些情况不太建议使用Serverless技术呢
我们之前选入的场景都具有“运维门槛较高需要免运费和全托管”“流量变化较大需要弹性伸缩”“轻量应用需要快速交付”“流量不确定需要能缩容至0按需使用按量付费”的特性那么反过来比如延时非常敏感的、SLA级别极高的场景比如类似网页搜索、银行交易就不太建议使用Serverless技术了。
在这里我也给你分享一个技巧你在初次接触Serverless的时候可以多参考云厂商官网的案例提工单和他们的售前工程师交流可以帮助你更好的来选型和用好他们的产品。虽然我前面的课程中已经给出了很多一线案例和经验但Serverless的发展是日新月异的紧贴官网是最好的选择之一。
资源评估
方案确定之后我们就要做资源评估了。虽然Serverless具备按需使用、按量付费的特点但这并不能说明Serverless的架构所产生的费用就比传统服务低。
你可以尝试按照这两个步骤评估:
第一,你的服务一天跑下来,是否存在明显的空闲期或者具备明显的“峰谷”现象?
第二,具备第一点后,是否选择了合适的资源规格去计算、对比各个方案费用?
这两点适用于所有选用Serverless技术的产品。我们拿函数计算来说它的收费是按照调用次数、资源使用耗时和出网流量来计算的。从各个云厂商的计价表可以看出主要的费用来自于这三点中的资源使用耗时而“资源耗时=内存大小*运行时间”。
从公式可以看出,资源的耗时成本是和内存大小、运行时间成正比关系的。在资源评估阶段,我们先说内存大小的问题。
我之前遇到一个客户他的调用次数每天大概是50W次每次执行在3秒左右但费用还不低。
通过平台监控我们发现他为了处理少部分数据量计算比较大的文件准备的是1G的内存这个数量只有不到1000次的调用量。
听到这里你有啥感想呢不急我们先来看一下这两种内存下的收费情况我以阿里云函数计算FC活跃实例资源价格计算如下
我们可以发现在不同的内存资源下费用相差4倍。所以当时我们给客户的建议是在第一个函数 Func1 中判断一下文件大小如果超过256MB承受的范围就通过异步策略发往下一个函数 Func2 处理这个函数设置为1GB就可以在比较低的成本下完成他的业务处理。
我们来看一下费用对比:
所以,在资源评估时,依据情况合理地进行函数拆分,也是至关重要的。
调用速度
刚才公式里面的第二个关键因素是“运行时间”,这就和调用速度相关了。那影响调用速度的因素有哪些?或者说,调用速度卡在哪里了呢?
从我跟客户打交道的经验来看常见的有这么几个点也是代码编程中容易忽视Serverless这种开发模式的地方。
代码包太大引入了不必要的依赖包这种情况尤其在Java的开发者中特别常见要善于用exclude去掉一些不相关的依赖。
运行时的影响之前我的一个客户由于使用了Java导致出现偶发的超时错误发现就是冷启动的时候耗时较长后来干脆替换成了Python就没有这种问题了。尽管在阿里云等厂商对Java的运行时做了优化但还记得我之前在运行时小节中跟你对比的么Java的耗时除了在冷启动在Invocation阶段也比Golang要长。
调用下游服务返回慢:要知道,函数是按照使用次数和时长来计费的,抛开这个不说,函数的超时时间设定的限制,如果太慢的下游服务返回,会出现超时错误。不仅浪费成本,还使得服务体验不好。
代码习惯问题比如引入不必要的框架它确实可以加快开发的速度但也会影响服务的速度另外就是不必要的循环和Sleep关键字在代码中的使用这些都是在设计函数代码架构和逻辑中格外需要注意的。
总结下来攻克这些问题需要做的就是两件事一个是函数特性的优化另一个是函数之间的协作优化。那么作为一名Serverless平台的用户具体可以做些什么呢
在函数特性优化方面你可以做5件事
尽可能减少不必要的代码依赖,优化代码体积,提升代码的下载和加载速度;
选择性能较高的运行时提升函数的启动速度比如Golang语言
合理利用本地缓存,对于比较大的数据,可以适当缓存在挂载路径中;
预留实例。我们知道Serverless的实例在没有流量进来的时候是会缩容掉的那么下次再有流量进来就会进入冷启动的流程你可以在成本允许的范围内对部分延时敏感性较高的函数设置一定的实例进行预留和分策略加载
请求预热。你可以通过配置一个定时触发器的方式,来主动调用函数来请求预热,设置的时间间隔你可以根据云厂商的实例回收时间来灵活配置。
开发模式。尽量让自己的代码在一层的处理逻辑中,以“平铺”的方式解决,避免层层嵌套、循环、停顿这种在微服务或者脚本上经常使用的习惯发生。
针对函数之间的协作,你同样可以做如下优化,来提升调用的速度:
尽可能使用异步调用,尤其是级联的函数调用避免同步调用下游服务产生的耗时,因此我们在选型的时候得要注意评估;
一个函数只做一件事情,也就是说要根据业务进行合理的函数粒度拆分。在成本、复用性、性能上都存在其必要性。
这样的优化能带来什么好处呢相信学过冷启动的你能立马回答出来提升服务的体验。如果你是一个HTTP网站服务响应越慢用户的流失也就越严重间接上你的页面访问和流量也会降低最后影响的是营收。
开发技巧
接下来,我们就到了开发阶段的讨论了。我会从开发工具选择以及编码技巧两个方面切入,这也是我们工作中最重要的两个抓手。
工具的选择
先说工具的选择。一般云厂商都会提供各种方便的工具来支撑项目的开发、调试、打包、发布和运维实现项目全生命周期的管理能力。比如阿里云的Serverless Devs腾讯云的Serverless Framework CLI百度智能云的BSAM等等。
开发工具一般分为三种本地开发工具CLI、WebIDE和IDE插件集成。其中WebIDE的能力更偏向支持轻量化的在线开发管理IDE插件的能力更偏向照顾那些使用成熟IDE的技术人员如VSCode的开发人员。
那面对这些工具我们该怎么选呢?
如果你的业务比较简单采用的又是解释型语言那么首选WebIDE关于它的优势和好处可以在回到第11节课回顾一下加深一下记忆
如果你的业务比较复杂或者是编译型语言那么我推荐你使用本地CLI工具或者插件集成。
这几类工具的区别在于如果你希望交互体验好一点并且对类似VSCode的IDE工具开发的比较顺手了那么将插件绑定在编辑器上是一个不错的选择。而类似Serverless Devs的这种工具如果你是富有极客精神的命令行狂热爱好者你可以用起来丰富的命令足可以支撑你完成项目的管理工作了。
编码技巧
有了开发工具,那编码有啥需要注意的呢?一方面,是资源的初始化复用思想;另一方面,是函数业务的调用和设置细节。我们通过一个例子来看一下。
我在运行时小节中跟你提到过基于标准运行时构建的函数其实是基于一个代码框架运行的。平台提供给你的是一个handler的入口函数你可以直接在这个函数里编写你的业务代码逻辑。但如果函数需要和资源打交道那么就需要在执行存储操作之前先建立连接了。
如果我们在handler函数中写了如下一段连接数据库的代码想一想这会有啥问题
是不是每次请求过来都要重新连接做一遍这个操作?如果这是一个偶尔触发一次的函数,可能看不出问题。但如果一旦并发量比较高的服务场景,就会极大的影响性能,还可能导致数据库的连接句柄超限。
import pymysql
def handler(event, context):
db =pymysql.connect(
host=os.Getenv("MYSQL_HOST"),
port=os.Getenv("MYSQL_PORT"),
user=os.Getenv("MYSQL_USER"),
passwd=os.Getenv("MYSQL_PASSWORD"),
charset='utf8',
db=os.Getenv("MYSQL_DBNAME")
)
cursor = db.cursor()
正确的做法应该把它单独拎出来,放到一个函数中,然后单独调用一次,这样在函数实例被回收之前,如果有新的请求过来,就可以直接复用了。
这个解决方案不仅利用了FaaS平台的实例复用技术也在实例复用的基础上复用了资源对象。如果你还想进一步优化也可以在给数据库对象db赋值和获取的时候判断是否为Null值使得代码更鲁棒。类似地像kafkaClient、redisClient等中间件资源的初始化都可以这样进行。
资源的初始化这个关键问题非常关键一旦处理不好可能还会导致资源服务的连接超限等问题除此以外根据客户常见的业务逻辑问题我综合选取了所有技巧中常用、高效方面的TOP5希望你能灵活用起来。
首先print日志的时候尽可能少而精。如果你使用的是云平台直接print“event”这种整个结构体很可能会撑爆日志的限制。所以尽量打印出你需要的业务字段。
其次尽量使用异步策略代替微服务形态下的异步框架。假如你在原生的微服务中使用Python的Tornado框架你会发现FaaS形态的Serverless是很难发挥其异步的价值的。这个时候你就可以直接选用我在第3讲高级应用中跟你提到的FaaS平台的异步处理框架。
再次,调用下游服务的接口,设置的超时时间一定要小于函数的超时时间。否则会因为短板在下游,而造成一次请求超时。浪费成本不说,也会让服务不稳定。
另外,要将公共代码放到层上。这也是我在高级属性这一节中跟你提到的必备高级技能之一,它类似于我们平时的公共类库,可以让具体的函数代码包更轻量。
最后提前设置并发数的上限。一般云厂商都会设置默认的实例并发数比如阿里云FC限定300 * InstanceConcurrency百度智能云CFC限定单实例100等这对于一个并发量稍微高一点的生产应用来说是不够的你需要提前设置申请扩大并发度。
线上运维
开发完代码发布到线上后有没有想当然的认为Serverless就是“免运维的”虽然我们多次强调过Serverless免运维的特性但上线后的服务稳定性、访问指标以及可观测等问题也是需要关注的。我们着重说一下稳定性和可观测。
稳定性方面,云厂商设置的异步调用策略,可以确保失败后的请求重试,预留实例可以确保流量突增的响应及时性。
除此之外我之前遇到的一位客户简单的方法也很值得借鉴。这位客户是一个在线的网站对重要接口采用轮训模拟请求的方式进行探活检测当出现连续N次出现问题的时候就会报警和切换到备用集群、备用区域。
你会发现在Serverless云厂商还不是很完善的情况下作为一个开发者可以基于“免运费”之上做一层“运维保险”。这个方式不一定最优但确实很实用我们交流之后也发现对保障服务的稳定和客户的体验都有明显的效果。
可观测方面,除了我在可观测小节中跟你细聊了通过指标、日志、链路三大支柱实现一个监测系统的机制,从使用的经验上,我也建议你“活”用云厂商关联的支撑服务。他们的监控仪表盘足以支撑你常用的指标,你还可以通过关联的报警服务、链路追踪服务来更全面地“问诊”服务。
小结
最后我们来小结一下。今天我给你介绍了Serverless实战中的一些使用经验包括方案选型、资源评估、调用速度、开发技巧、线上运维这一个完整生命周期里的心得。
你会发现这节课我多次提到了在第1、2模块中的知识点。比如在调用速度里你可以关注冷启动、函数之间调用这两节课在开发技巧方面你可以着重关注WebIDE、高级应用这两节课在线上运维方面可以更多地关注可观测的内容。
这节课不一定能够解决你在实战过程中遇到的所有的问题,但一定能够作为你的知识地图,帮助你定位每一个困惑背后需要不断精进的知识点。希望能够让你在开始接下来的实战进阶课之前,串联起讲解过的技术细节,形成自己的知识网络。
随着Serverless的不断演进未来的众多产品也一定会朝着Serverless的形态转变。你在后续的工作中还会遇到更多的业务诉求转型、难点挑战希望你也能一个一个找到更优的解决方案并沉淀成方法分享给更多的Serverless前行者。
后续的实战课中我们将一起针对性地练习Serverless技术中的5大核心场景连接云生态、跨平台开发、传统服务的迁移、私有化部署和引擎底座选取以及基于引擎构建平台。准备好了吗
思考题
好了,这节课到这里也就结束了,最后我给你留了一个思考题。
你在使用Serverless的过程中还有哪些“踩坑”经验或者你在技术选型的时候还有哪些疑惑的地方
欢迎在留言区写下你的思考和答案,我们一起交流讨论。
感谢你的阅读,也欢迎你把这节课分享给更多的朋友一起阅读。