Serverless架构:从原理、设计到项目实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2 优势与劣势

Serverless架构并不是脱离了服务器或者不需要服务器,而是意味着去除有关对服务器运行状态的关心和担心,例如对服务器是否在工作、应用是否正常运行等问题,不需要关心和担心,这不仅是Serverless架构的一个特性,更是其给予开发者的便利,也是其一大优势。除此之外,Serverless架构的其他优势也是非常明显的,包括Serverless架构本身的优点,以及用户使用Serverless架构时可以带来的开发优势、体验优势等。

Serverless架构的优势主要包括降低运营成本和开发成本,拥有优秀的扩展能力、更简单的管理,以及符合“绿色”计算的思想。在使用传统服务器的时候,我们的服务器每时每刻的用户量是不同的,资源使用率也是不同的,可能白天资源使用率比较合理,夜间就会出现大量资源闲置。按照《福布斯》杂志的统计,企业数据中心的典型服务器使用率仅5%~15%,这无疑是一种资源的巨大浪费。而Serverless架构的出现,则可以让用户委托服务提供商管理服务器、数据库和应用程序甚至逻辑,这样做一方面减少了用户自己维护的麻烦,另一方面用户可以根据自己实际使用函数的粒度进行成本的支付。对于服务商而言,他们可以将更多的闲置资源进行额外的处理,这从成本的角度、“绿色”计算的角度来说,都是非常不错的。

对于用户和开发者而言,Serverless架构有降低人力成本、降低风险、减少资源开销、增加缩放灵活性、缩短创新周期等优点,如图1.6所示,使用Serverless架构,用户不需要再自己维护服务器,也不需要自己操心服务器的各种性能指标和资源利用率,可以有更多的时间和精力去关心和关注应用程序本身的状态和逻辑。同时Serverless应用本身的部署十分容易,我们只要上传基本的代码即可,例如Python程序只需要上传其逻辑与依赖包,C/C++、Go等程序只需要上传其二进制文件,Java程序只需要上传其Jar包等,无须使用Puppet、Chef、Ansible或Docker来进行配置管理,这大大降低了运维成本。对于运维来说,Serverless架构也不再需要监控底层的数据,例如磁盘使用量、CPU使用率等,可以更加专注地将监控目光放到监控应用程序本身的度量上。在Serverless架构下,运维人员的工作角色会有所转变,部署将更加自动化,监控将更加面向应用程序本身。

图1.6 传统项目上线和Serverless项目上线对比图

在降低风险层面,对于组件越多、结构越复杂的系统,出故障的风险就越大,而在Serverless架构下,很多模块都可以托管给服务商,例如存储系统、API网关系统等,对于传统项目中需要我们自己维护的触发模块、路由模块、存储模块,我们不再直接维护,如果出现问题,可以交给服务商来处理,让服务商的专业人员来处理有时候比我们自己来处理更可靠,利用专业人员的知识来降低停机的风险,缩短故障修复的时间,可以让我们的系统稳定性更高。当然,这一点也充分说明,找到一个专业的服务商是非常必要的。

在传统项目上线过程中,需要申请主机资源,这时候一般会评估出一个峰值(最大开销),再根据峰值来申请资源,这意味着即使在主机闲置的状态下也要支付峰值容量的开销,往往会导致主机资源过度配置。对于某些应用来说这是不得已的做法,比如数据库这种很难扩展的应用。而对于普通应用这就显得不太合理了,虽然很多时候我们都觉得即使浪费了资源也比当峰值到来时应用程序因为资源不足而无法提供服务好。这个问题最好的解决办法就是,不计划到底需要使用多少资源,而是根据实际需要来请求资源,当然前提是整个资源池里的资源是充足的(公有云显然更适合)。根据使用时间来付费,根据每次申请的计算资源来付费,让计费的粒度更小,将更有利于降低资源的开销。这是对应用程序本身的优化,例如让每次请求耗时更短,让每次消耗的资源更少,将能够显著节省成本。

如图1.7所示,以腾讯云SCF(Serverless Cloud Function)为例,当平台接收到第一个触发函数的事件时,它将启动一个容器来运行代码。如果此时收到了新的事件,而第一个容器仍在处理上一个事件,平台将启动第二个代码实例来处理第二个事件。SCF的这种自动的零管理水平缩放,将持续到有足够的代码实例来处理所有的工作负载为止。

图1.7 函数自动弹性伸缩示意图

除了上述各种优势,Serverless也更容易上手操作,有利于提升团队效率,降低人力成本。2019年8月,在腾讯云位于深圳的技术沙龙中,“乐凯撒”团队的同学对其项目中的两个使用了Cloud Function的模块进行了分享,其中一个是云打印服务,通过使用腾讯云Cloud Function提供的Web Socket服务,避免了难度较大的底层框架的开发,研发人员只要关注业务开发即可,一个人大概花了2周时间就完成了项目开发,人力和时间成本至少节约50%;另一个例子是会员花销标签计算系统,使用CMQ、API网关和Cloud Function快速搭建起来一个高性能的计算服务架构,一个中级研发工程师(3年经验)从研究使用方法到搭建框架再到开发完成用了不到两周时间参考地址[3]。。通过这两个生动形象的例子,我们可以看到,Serverless架构可以使用短而简单的函数和事件来黏合强大的驱动数据存储和服务的API。完成的应用程序具有高度可用性和可扩展性,利用率高,成本低,部署速度快,可以大大节约时间成本和人力成本。如果说以Docker为代表的容器技术缩短了应用程序的迭代周期,而Serverless架构则直接缩短了创新周期——从概念到最小可行性部署的时间,让初级开发人员也能在很短的时间内完成以前通常需要经验丰富的工程师花很长时间才能完成的项目。

当然,所有事情都有“利”的一面,也有“弊”的一面,Serverless架构也是如此,它在为我们提供便利的开发模式、开发策略的同时,为我们提供优秀的底层服务的同时,为我们提供按量使用服务的同时,也暴露出了一些劣势。例如Serverless架构难以进行状态管理,要想实现自由缩放,无状态是必需的,而对于有状态的服务,使用Serverless就会丧失其灵活性,有状态服务需要与存储交互就不可避免地增加了延迟和复杂性。说到增加延迟,就不得不说Serverless架构的另一个劣势,那就是由冷启动带来的延迟问题,应用程序中不同组件的访问延迟是一个大问题。Serverless应用程序是高度分布式、低耦合的,这就意味着延迟将始终是一个问题。由于不同的云厂商或者不同的开源框架都有不同的入参格式,并且不同的触发器也有不同的格式,以腾讯云的Serverless产品为例,其入参有event和context参考地址[4]。。通过event入参对象,云函数代码可以与触发函数的事件(event)交互;通过context入参对象,代码将能了解到运行环境及当前请求的相关内容。不同触发器的event的格式也不尽相同,例如腾讯云CMQ触发器的event格式模板为:

        {
          "Records": [
            {
              "CMQ": {
              "type": "topic",
              "topicOwner":123456789,
              "topicName": "testtopic",
              "subscriptionName":"xxxxxx",
              "publishTime": "1970-01-01T00:00:00.000Z",
              "msgId": "123345346",
              "requestId":"123345346",

              "msgBody": "Hello from CMQ! ",
              "msgTag": ["tag1", "tag2"]
            }
          }
        ]
        }

Ckafka触发器的event格式为:

        {
          "Records": [
            {
              "Ckafka": {
              "topic": "test-topic",
              "partition":"",
              "offset":123456,
              "msgKey": "asdfwasdfw",
              "msgBody": "Hello from Ckafka! "
              }
            }
          ]
        }

正是这种厂商之间的入参内容不一致,不同触发器的参数格式不一致,导致了Serverless架构项目本地测试难度相对较大,这是一个很棘手的问题。虽然可以在测试环境下使用各种数据库和消息队列来模拟生产环境,但是对于Serverless应用的集成或者端到端测试尤其困难,很难在本地模拟应用程序的各种连接,并与性能和缩放的特性结合起来测试,并且Serverless应用本身也是分布式的,简单地将无数的FaaS和BaaS组件黏合起来也是有挑战性的。

除了上述劣势,Serverless架构还有语言版本落后、完全依赖于第三方服务等缺点。

就目前而言,无论是AWS还是腾讯云或者Google云,其Serverless相关产品所支持的Runtime都是有限的,很多语言版本不能及时更新已经成为共性问题,以AWS为例,在Node.js 6出来的时候,AWS Lambda只支持到Node.js 4.3.2;在Node.js 9出来的时候,AWS Lambda仅支持到6.10.3。

由于Serverless过分依赖服务商,例如一个网站业务使用Serverless可能需要绑定服务商的API网关、对象存储、数据库、云函数等众多产品,而且每个服务商的函数之间的编排规则、event参数的格式又不一样,就会导致更换服务商困难重重。例如,目前用户在AWS上部署了一套基于Serverless架构的网站后端服务,那么此时想要将这个业务迁移到Google云上,基本上要对全部函数进行改造,这是非常有风险的,且要投入很大精力。

总结一下,Serverless的技术特点就是按需加载、事件驱动、状态非本地持久化、非会话保持、自动伸缩和应用函数化,其优势就是节约成本(包括时间成本、人力成本等)、减少运维需求、缩短迭代周期。同时Serverless架构也有与云厂商高度耦合、难以解绑,冷启动问题严峻,函数编排较困难等劣势。但是我们不可否认,Serverless正在以我们肉眼可见的速度快速地发展。