Serverless/Faas/BaaS 等概念在这几年的技术圈中是绝对的热点词汇之一,国内外众多云厂商也纷纷推出自家的 Serverless 和函数计算产品,微信也依托腾讯云推出了基于 Serverless 和 FaaS 理念的「小程序·云开发」,对应的新型岗位也不断涌现。

如今,我们确实看到很多中小型业务在拓展新领域、开发新功能时会优先考虑使用 Serverless 产品作为后端架构基建,但却鲜有见到面向 C 端的一线大厂中,有核心业务在 Web 后端层面改为采用 Serverless 作为开发模式,这又是何缘由呢?

什么是Serverless

作为业界 Serverless 和 FaaS 领域的先锋,Amazon 的 Serverless 产品页面对 Serverless 作出了这样的定义:

无服务器是一种用于描述服务、实践和策略的方式,使您能够构建更敏捷的应用程序,从而能够更快地创新和响应变化。凭借无服务器计算,容量预置和补丁等基础设施管理任务由 AWS 处理,以便您能够专注于编写为客户服务的代码。AWS Lambda 等无服务器服务具有自动扩展、内置高可用性以及按价值付费的计费模型。Lambda 是一种事件驱动的计算服务,使您能够运行代码来响应来自 200 多个本地集成的 AWS 和 SaaS 源的事件 — 所有这些都无需管理任何服务器。

根据 Amazon 的定义及各个厂商和业务对 Serverless 的实践,我们可以进一步将 Serverless 的特点归纳如下:

  • 解耦开发与运维:业务只需要关心自身的业务实现,不需要关心机器情况,也无需进行复杂的基础组件配置甚至环境搭建。
  • 弹性:借助于近几年容器技术的发展,可实现毫秒级快速扩容,并可根据流量弹性扩缩容。
  • 按需付费:借助弹性伸缩能力,使用者无需大量冗余机器,按需扩缩容,根据请求量等指标快速冷启动,进而按需付费降低成本。
  • 精细计费:理想情况下 Serverless 架构中的每个原子应用都应该是基本无副作用的函数,各函数可各自弹性扩展,进而实现函数级别的细粒度计费。

极速扩容并不极速

借助于容器技术的发展,Serverless 可做到毫秒级别的新容器弹出,如果是 Runtime 类型的实现,函数初始化速度还会更快,云层面的「极速扩容」是可行且实用的。

然而在应用层面,虽然 Web 后端服务本身通常是无状态的,但为了根据请求返回对应的业务数据,应用还要与有状态的 DB 、Redis 等持久层进行交互,内网的微服务间也需要相互连接以进行通信,这通常都是基于 TCP 长连来进行的。而由于创建连接本身就是一件很耗时的事情,再加上有的组件为了避免建连过程中的并发问题采用了串行建连,后端为了提升性能、避免服务因建连而导致的卡顿通常会在应用初始化过程中、向外提供服务前就通过建立一批预留连接的方式来池化连接,再加上 Java 类应用本身还有 JVM 即时编译器需要逐步优化字节码导致的初启动时性能差的问题,Web 后端应用的启动常常至少是分钟级别的,在这样的耗时比较下,毫秒级的容器或函数初始化能力只能说一定程度上优化了应用启动的耗时,却不能称其为解决了整个链路的快速扩容问题。

试想如果 C 端的 Web 后端服务完全依赖 Serverless 的弹性伸缩,不再根据预估的流量变化进行机器冗余,甚至流量到来时才冷启动函数,那么在秒杀、其他系统雪崩带来的流量大幅上涨的情况下,一旦出现扩容速度慢于流量上涨速度的情况,服务将被瞬间打垮。

另一方面,按用量扩容的逻辑通常会有并发度的限制,以便于扩容时可做到尽量准确进而尽量贴近按需付费的设计。但不同类型服务的监控项和监控阈值不尽相同,平台很难不依赖业务压测报告就能智能给出准确结论。而在突发流量的场景下,按并发度扩容受限于上文提到的应用部署时间长的问题,很有可能出现扩容速度追赶不上流量上涨速度的问题。

按需付费难以实践

结合极速扩容在实际后端场景的局限性,中大型 Web 后端服务往往会更倾向于仍然按传统的「人工评估流量峰值」、「压测确定单机性能」、「按压测结论提前手动扩容进行冗余」和「回归压测集群性能是否可满足目标」的流程来进行流量运维。但同时,后端通常对弹性扩缩容接受度很高,因此会在手动扩容的同时接入 Serverless 的弹性伸缩能力来保证极端流量发生时有扩容的兜底手段。也就是说,很多场景下,后端仍要和过去一样冗余机器来应对流量,成本很难实质性地被降低。而如果公司的基建是自建的云体系,那么弹性伸缩意味着需要预留机器资源池用于扩容,所以整体的实际成本相较传统方式可能还会有所上升。

中大型Web后端逻辑难以真正函数化

在 C 端业务发展的初期,从 MVP 到产品全量上线,后端逻辑大多面临着两天一小改、三天一大改的需求迭代状态,所以初期的代码结构、架构设计都很难做到足够合理化。而如果产品能存活到稳定期,那么在没有明确的性能、扩展性问题的情况下,大部分团队都只会选择以打补丁的方式进行迭代而非大范围重构优化。这样一来,合理的函数化微服务设计对于存量服务来说也就很难落地。

那么如果在业务创建伊始就采用函数化的设计呢?我们知道 FaaS 在后端领域通常意味着更加精细的微服务拆分设计。在微服务大行其道的当今,很多业务会采用 DDD 的思想进行领域划分进而自然而然地形成自洽的微服务体系。但微服务间调用的耗时增加、可用率低于单体服务、调用关系需要配置复杂的熔断降级策略等问题都是客观存在的,微服务体系实际上是在性能和架构合理性之间找寻平衡点。如果将微服务再进一步拆分为更加细化的函数,那么虽然架构的合理性可能得以进一步提升,但业务整体的性能和稳定性问题的复杂程度将会有一个数量级的上升。

既然将微服务进一步拆分为函数难以落地,那直接以原有的微服务作为函数呢?这样确实可行,可是传统架构依赖容器技术的进步已经足以支撑此类业务的发展,Serverless 的优势将只剩下运维层面的便捷,但上文中也讲到所谓的运维优势在 C 端场景中很难发挥实际作用,后端业务又有什么特别的理由必须选择 Serverless 呢?

开发模式的巨大差异

对于 Web 后端常用的 Java 体系来说,Spring 已经成为了既定的标准,而目前的 FaaS 实现通常需要在代码中配置触发器消息的消费者来实现功能定义,同时常常需要搭配 Runtime SDK 负责应用启动,这与传统的 SpringMVC 等组件的开发思路差异较大,除了需要开发人员改变开发习惯、积累新的开发经验外,存量的服务也将面临着巨大的改造成本。

即使脱离语言的特定场景,不同云厂家提供的 SDK 也不尽相同,这也就意味着更换服务商需要修改代码逻辑、重新测试回归功能。而对于能靠自身能力提供一揽子 Serverless 方案的大厂,其 SDK 在可预见的未来不会有根本上的变化。可一旦出于性能等问题的考虑,服务需要迁回 PaaS 类架构,或未来技术革新有了 FaaS 理念的替代者,那么工程师们所要面对的改造成本仍然十分巨大,如若处理不好,当年对前沿技术的实践就可能会变为沉重的技术债。

Serverless真的无法应用于传统后端吗?

对于 Serverless 的适用场景,阿里云的文档给出了如下理解:

  1. 事件触发的计算
  2. 实时视频广播的弹性调整大小
  3. 物联网数据处理
  4. 共享交付调度系统

可见,目前商用的使用场景大多集中在对响应耗时不敏感或完全异步的场景,那么传统的 Web 后端项目真的就无法适应 Serverless 架构了吗?

相比起传统的 PaaS 架构主要针对的是运维资源交付场景,FaaS 需要开发者显式地参与到函数的编写、配置和部署流程中,因此 FaaS 实际上是包含面向研发开放的理念的。既然如此,我们或许应该减少对于 Serverless 运维层面优势的讨论,聚焦于开发层面的问题解决。

函数内联

目前的 FaaS 平台中,函数定义大多与服务无异,函数间的调用仍然要通过网络调用进行。而如果我们将 FaaS 作为后端微服务的进阶状态,我们拆分的函数功能必然会更加干练,上下游依赖也会更加繁多,只将其作为独立服务向外提供功能就意味着必然会造成耗时的上涨、稳定性的降低,同时被加长了的调用链路也会提升维护难度。因此如果可以将云中的函数与代码中的函数的定义打通,向基础函数提供进程内通信方案,那么后端进行函数化改造的顾虑将会低很多,可行性也会有质的提升。

函数结构化

在微服务的架构下,每个服务的上下游依赖梳理向来都是件耗时耗力的工作。而如果将微服务拆分为更小的函数,那么虽然我们解决了哪些逻辑该拆为微服务、拆多少个微服务的问题,但梳理子域中数量庞大的函数间的逻辑关系将会让人更加望而却步。

因此我们需要建立一套基于函数理念的结构化视图,函数在定义时可以与服务是多对多的关系,在运行时函数实例与服务是多对一的关系,即函数组成服务,服务向外提供统一业务能力。

另一方面,有了结构化的函数视图和管理能力后,我们也有了将函数进行抽象公用、建立函数市场概念的可能,进而便可以一定程度上解决重复开发的问题。

消除开发模式差异

对于不同厂家 SDK 差异大、相互不兼容的问题,Spring 给出了 Spring Cloud Function 这个答案。Spring Cloud Function 的设计有些类似于 ORM 框架的理念,提供统一的 API ,底层可根据配置对接不同的 FaaS 方案,这样一来平台迁移的成本就被降到了最低。同时,我们还应考虑存量业务如何进行函数化改造以及已有的 FaaS 项目如何回退到传统架构的问题,做到向前和向后兼容,进而最大程度降低 FaaS 的接入成本,打消业务对 Serverless 架构发展前景的顾虑。

此外,目前对于如远程调试、链路追踪、日志统计等功能,平台给出的解决方案与成熟的开发模式也有着较大差异,而对于 Java 项目来讲 Runtime 类型的 FaaS 实现相当于做了调试能力的功能阉割,因此平台也需要迭代出与成熟开发模式相持平的能力,提高业务的研发和问题排查效率。

新老结合的伸缩方式

对于大流量的 C 端 Web 业务来说,完全依赖 Serverless 的弹性扩容来根据调用进行冷启动是不现实的,因此平台也需要支持传统架构的冗余部署策略,同时结合平台已有的弹性伸缩能力来一定程度地降低业务冗余倍数进而降低费用,并以此提供突发流量的兜底扩容方案。

博客链接:https://easonyang.com/2021/06/05/serverless-and-backend/

关注公众号「举一得一」获取最新文章更新

Serverless与Web后端天生不合?的更多相关文章

  1. 实现 Web 后端和客户端之间的分布式和认证通讯

    stack.io 是一个用于实现 Web 后端和客户端之间的分布式和认证通讯. 服务器端进程之间的通讯是非常高效的,因为没有中间的代理.而来自客户端的请求通过 socket.io 进入 Node.js ...

  2. 8.app后端和web后端的区别

    很多从web后端转到app后端的小伙伴经常很茫然,不知道这两者之间有啥区别.本文通过例子,分析web后端和app后端的区别,使各位更好地把握app后端的架构. (1) app后端要慎重考虑网络传输的流 ...

  3. 杂记:腾讯暑期实习 Web 后端开发面试经历

    今天面试(一面)腾讯暑期实习 Web 后端开发,一言难尽. 第一部分,常规的自我介绍. 介绍完,面试官问我对人工智能有什么理解?深度学习和机器学习的区别?对调参有什么见解?语音识别中怎样运用了机器学习 ...

  4. Web前端 Web前端和Web后端的区分

    一.绪论 1. 前台:呈现给用户的视觉和基本的操作. 后台:用户浏览网页时,我们看不见的后台数据跑动.后台包括前端.后端. 前端:对应我们写的html.css.javascript 等网页语言作用在前 ...

  5. 转载关于Python Web后端开发面试心得

    先介绍下我的情况:通信背景,工作一年多不到两年.之前一直在做C++的MFC软件界面开发工作.公司为某不景气的国企研究所.(喏,我的工作经验很水:1是方向不对:2是行业有偏差).然后目前是在寻找Pyth ...

  6. Web前端和Web后端的区分

    版权声明:本文为CSDN博主「十豆三展」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/zz1399590022 ...

  7. 单机Web后端接口服务压力测试

    单机Web后端接口服务压力测试 工具:Apache jmeter 环境:Window 10 语言:Kotlin + java 架构:SpringBoot + + Mysql + redis + Spr ...

  8. Web 后端的一生之敌:分页器

    分页器是 Web 开发中常见的功能,看似简单的却经常隐藏着各种奇怪的坑,堪称 WEB 后端开发的一生之敌. 常见问题 边翻页边写入导致内容重复 某位用户正在浏览我的博客,他看到第一页最后一篇文章是 & ...

  9. 基于 Sequelize.js + Express.js 开发一套 Web 后端服务器

    什么是 Sequelize 我们知道 Web 应用开发中的 Web 后端开发一般都是 Java.Python.ASP.NET 等语言.十年前,Node.js 的出现使得原本仅限于运行在浏览器中的 Ja ...

随机推荐

  1. Django框架中logging的使用

    Django框架中logging的使用 日志是我们在项目开发中必不可少的一个环节,Python中内置的logging已经足够优秀到可以直接在项目中使用. 本文介绍了如何在DJango项目中配置日志. ...

  2. 编写CUDA内核

    编写CUDA内核 介绍 与用于CPU编程的传统顺序模型不同,CUDA具有执行模型.在CUDA中,编写的代码将同时由多个线程(通常成百上千个)执行.解决方案将通过定义网格,块和线程层次结构进行建模. N ...

  3. sql优化_隐式-显示转换

    ========  测试表1信息   =======SQL> select count(*) from tb_test; COUNT(*)----------   3000000   SQL&g ...

  4. Android adb的常用命令

    环境部署: 1.下载adb工具 2.下载奇兔刷机(或其它一键刷机软件),将手机与电脑进行连接 3.一键root手机 命令 1.获取设备列表及设备状态:adb devices  如果连接的设备不止一个, ...

  5. 【NX二次开发】Block UI 列表框

    属性说明 常规         类型 描述     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical ...

  6. 生成树协议(STP)

    一.交换网络环路的产生 1.广播风暴的形成 2.多帧复制 3.MAC地址表紊乱 二.STP简介 STP-Spanning Tree Protocol(生成树协议) 逻辑上断开环路,防止广播风暴的产生 ...

  7. nacos 实战(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...

  8. VBS脚本编程(10)——编写WMI脚本

    WMI介绍 1.WMI是什么? WMI--Windows管理规范(Windows Management instrumentation). 是一项核心的Windows管理技术. 采用统一的.基于开放标 ...

  9. Unity3D学习笔记1——绘制一个三角形

    目录 1. 绪论 2. 概述 3. 详论 3.1. 准备 3.2. 实现 3.3. 解析 3.3.1. 场景树对象 3.3.2. 绘制方法 4. 结果 1. 绪论 最近想学习一下Unity3d,无奈发 ...

  10. 精尽Spring Boot源码分析 - 文章导读

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...