谈完云计算后我们不得不说的云服务类型。
看如下图清晰的带你了解云服务类型
image.png
大多数云计算服务都可归为四大类:基础结构即服务 (IaaS)、平台即服务 (PaaS)、无服务器(FaaS)和软件即服务 (SaaS)。它们有时候称为云计算“堆栈”,因为它们互为构建基础。了解这些服务及它们之间的差异,可使你更轻松地实现业务目标。

  1. # 基础结构即服务 (IaaS)
  2. 云计算服务的最基本类别。使用 IaaS 时,你以即用即付的方式从服务提供商处租用 IT 基础结构,如服务器和
  3. 虚拟机 (VM)、存储空间、网络和操作系统
  4. # 平台即服务 (PaaS)
  5. 平台即服务 (PaaS) 是指云计算服务,它们可以按需提供开发、测试、交付和管理软件应用程序所需的环境。
  6. PaaS 旨在让开发人员能够更轻松地快速创建 Web 或移动应用,而无需考虑对开发所必需的服务器、存储空间、
  7. 网络和数据库基础结构进行设置或管理。
  8. # 无服务器计算(FaaS)
  9. 使用 PaaS 进行重叠,无服务器计算侧重于构建应用功能,无需花费时间继续管理要求管理的服务器和基础结构。
  10. 云提供商可为你处理设置、容量规划和服务器管理。无服务器体系结构具有高度可缩放和事件驱动特点,且仅在
  11. 出现特定函数或事件时才使用资源。
  12. # 软件即服务 (SaaS)
  13. 软件即服务 (SaaS) 是通过 Internet 交付软件应用程序的方法,通常以订阅为基础按需提供。使用 SaaS 时,
  14. 云提供商托管并管理软件应用程序和基础结构,并负责软件升级和安全修补等维护工作。用户(通常使用电话、
  15. 平板电脑或 PC 上的 Web 浏览器)通过 Internet 连接到应用程序。

接下来我们来谈云服务类型的区别

IaaS,PaaS,SaaS 的区别

  1. IaaS:基础设施服务,Infrastructure-as-a-service
  2. PaaS:平台服务,Platform-as-a-service
  3. SaaS:软件服务,Software-as-a-service

它们有什么区别呢?
IBM 的软件架构师 Albert Barron 曾经使用披萨作为比喻,解释这个问题。David Ng 进一步引申,让它变得更准确易懂。
请设想你是一个餐饮业者,打算做披萨生意。
你可以从头到尾,自己生产披萨,但是这样比较麻烦,需要准备的东西多,因此你决定外包一部分工作,采用他人的服务。你有三个方案。

  1. # 1)方案一:IaaS
  2. 他人提供厨房、炉子、煤气,你使用这些基础设施,来烤你的披萨。
  3. # 2)方案二:PaaS
  4. 除了基础设施,他人还提供披萨饼皮。
  5. 你只要把自己的配料洒在饼皮上,让他帮你烤出来就行了。也就是说,你要做的就是设计披萨的味道(海鲜披萨
  6. 或者鸡肉披萨),他人提供平台服务,让你把自己的设计实现。
  7. # 3)方案三:SaaS
  8. 他人直接做好了披萨,不用你的介入,到手的就是一个成品。你要做的就是把它卖出去,最多再包装一下,印上
  9. 你自己的 Logo
  10. # 上面的三种方案,可以总结成首页的那张图。
  11. 从左到右,自己承担的工作量(上图蓝色部分)越来越少,IaaS > PaaS > SaaS
  12. 对应软件开发,则是下面这张图。
  1. SaaS 是软件的开发、管理、部署都交给第三方,不需要关心技术问题,可以拿来即用。普通用户接触到的互联网
  2. 服务,几乎都是 SaaS,下面是一些例子。
  3. * 客户管理服务 Salesforce
  4. * 团队协同服务 Google Apps
  5. * 储存服务 Box
  6. * 储存服务 Dropbox
  7. * 社交服务 Facebook / Twitter / Instagram
  8. ------------------------------------------------------------------------------------------
  9. PaaS 提供软件部署平台(runtime),抽象掉了硬件和操作系统细节,可以无缝地扩展(scaling)。开发者只
  10. 需要关注自己的业务逻辑,不需要关注底层。下面这些都属于 PaaS
  11. * Heroku
  12. * Google App Engine
  13. * OpenShift
  14. ------------------------------------------------------------------------------------------
  15. IaaS 是云服务的最底层,主要提供一些基础资源。它与 PaaS 的区别是,用户需要自己控制底层,实现基础设施
  16. 的使用逻辑。下面这些都属于 IaaS
  17. * Amazon EC2
  18. * Digital Ocean
  19. * RackSpace Cloud
  1. # 整体而言:
  2. IaaS 是云服务的最底层,主要提供一些基础资源。
  3. PaaS 提供软件部署平台(runtime),抽象掉了硬件和操作系统细节,可以无缝地扩展(scaling)。开发者只
  4. 需要关注自己的业务逻辑,不需要关注底层。
  5. SaaS 是软件的开发、管理、部署都交给第三方,不需要关心技术问题,可以拿来即用。

那么BaaS和FaaS又是什么呢?

  1. # BaaSBackend as a Service(后端即服务)
  2. 服务商为客户(开发者)提供整合云后端的服务,如提供文件存储、数据存储、推送服务、身份验证服务等功能,
  3. 以帮助开发者快速开发应用。
  4. # FaaSFunction as a service(函数即服务)
  5. 无服务器计算,当前使用最广泛的是AWSLambada
  6. 服务商提供一个平台,允许客户开发、运行和管理应用程序功能,而无需构建和维护通常与开发和启动应用程序
  7. 相关的基础架构的复杂性。 按照此模型构建应用程序是实现“无服务器”体系结构的一种方式,通常在构建微服务
  8. 应用程序时使用。
  9. ------------------------------------------------------------------------------------
  10. `扩展`
  11. 其实还有很多的aaS,比如
  12. # DaaS(Data as a service,数据即服务)
  13. 数据即服务是指与数据相关的任何服务都能够发生在一个集中化的位置,如聚合、数据质量管理、数据清洗等,
  14. 然后再将数据提供给不同的系统和用户,而无需再考虑这些数据来自于哪些数据源。
  15. # NaaS(Network as a service,网络即服务)
  16. 网络即服务(Network as a ServiceNaaS)是一种旨在通过互联网提供网络服务的商业模式。
  17. 从客户的角度来看,他们只需要一台连接到互联网的计算机,以及访问NaaS提供商的门户。
  18. # CaaS(容器即服务)
  19. 容器即服务(CaaS)是一种云服务计算的模型,它允许用户使用内部数据中心或云,通过基于容器的抽象来部署和
  20. 管理应用。
  21. ......等等其他的aaS

下面我们着重讲下FaaS。

FaaS:Function as a service(函数即服务)

Faas,又一个未来?
FaaS,未来的后端服务开发之道
云计算时代出现了大量XaaS形式的概念,从IaaS、PaaS、SaaS到容器云引领的CaaS,再到火热的微服务架构,以及现在越来越多被谈起的Serverless和FaaS,我们正在经历?一个技术飞速变革的时代。
说 FaaS 先要说说 PaaS

PaaS(平台即服务

简单来说,PaaS 就是把计算能力放在线上,你只管写代码就行了,目的也是为了减少后端维护的成本,让开发者更关注到开发本身。国内有 Sina App Engine,国外有 Heroku、Google App Engine、Amazon Web Services,但是这类服务被真正用来做产品的并不多,大多是当作开发的试验田跑一下,而且跑起来的成本比独立部署个服务器也差不多,你要理解很多服务的相关性,应用运行时还有提供各种服务的桥接,就造成你需要去理解一大堆东西才能把他们五花大绑到一起,所以这类服务并没有成为真正的主流,更多的是还是用原生的计算能力,比如 Amazone EC2、AWS 这类 IaaS 平台,国内的阿里云、UCloud 等。
PaaS 有不少缺点。

1、对计算能力不可掌控

PaaS 将自己的运行时封装成了一个黑盒子,你要用他你就要基于这些黑盒子的约束和条件去自行判断,需要了解每个模块或者函数的可用性和限制是什么,才能更好的开发,为了避免应用有太高的权限造成安全问题,服务商往往的做法是裁剪,将限制的能力来提供给你,那么如果你要开发一个应用,本地能用,部署了可能会有各种兼容问题。
一个完整的应用,在基于 PaaS 去开发的时候,势必会有服务的依赖,对于这些服务的依赖,你也是没有掌控能力的,你只能基于给出的环境变量是去配置,但是往往在复杂应用中,对于服务的依赖非常深入,可能会有比较深入的使用和调优,这个只能束手无策。

2、线上开发调试模型复杂

一个完整的应用就是一个功能集合,开发调试起来是很麻烦的,想象一下如果一个很庞大的网站,有一大堆的功能,你依赖可能十几个甚至二十几个服务,跑在你不太知道的黑盒子,你的调试该多麻烦。如果是你自己的环境,你可以随意的开启 DEBUG 参数、去查看系统调用栈、去看硬件参数、去看系统优化参数、去分析运行时的细小问题、而在 PaaS 你能做的仅仅是通过服务商提供的一个后台来做一些简单的查看,日志的分析。这个决定了 PaaS 不适合一个有规模的产品去使用。

什么是Faas呢?

云计算时代出现了大量XaaS形式的概念,从IaaS(Infrastructure as a Service)、PaaS(Platform as a Service)、SaaS(Software as a Service)到容器云引领的CaaS(Containers as a Service),再到火热的微服务架构,它们都在试着将各种软、硬件资源等抽象为一种服务提供给开发者使用,让他们不再担心基础设施、资源需求、中间件等等,在减轻心智负担的同时更好地专注于业务。FaaS是Functions as a Service的简称,它往往和无服务架构(Serverless Architecture)一同被提起。

Serverless的概念刚刚出现在HackerNews时并不为大众所接受。后来随着微服务和事件驱动架构的发展才慢慢引起关注。Serverless并不是说没有服务器参与,它通过将复杂的服务器架构透明化,使开发者专注于“要做什么”,从而强调了减少开发者对服务器等计算资源的关注、工作粒度从服务器切换到任务的思想。2006年第一个支持“随用随付”的代码执行平台Zimki问世。2014年亚马逊AWS推出了Lambda成为最主要的无服务架构的代表。接着Google、IBM和Microsoft也纷纷推出了各自支持Serverless的平台。

微服务架构近年来是一个非常火爆的话题,大大小小的公司都开始逐步分拆原来的单体应用,试着转换到由各个模块服务组合成大型的复杂应用。Serverless可以看作是比微服务架构更细粒度的架构模式,即FaaS。Lambda也是FaaS的典型代表,它允许用户仅仅上传代码而无需提供和管理服务器,由它负责代码的执行、高可用扩展,支持从别的AWS服务或其他Web应用直接调用等。以电子商务应用为例,微服务中可以将浏览商品、添加购物车、下单、支付、查看物流等拆分为解耦的微服务。在FaaS里,它可以拆分到用户的所有CRUD操作代码。当发生“下单”事件时,将触发相应的Functions,交由Lambda执行。人们在越来越多的场景里将Serverless和FaaS等同起来。
云服务类型 - 图2
假设现在有下面的JavaScript代码:

  1. module.exports = function(context, callback) {
  2. callback(200, "Hello, world!");
  3. }

显然它是一个函数,通过FaaS的方式,我们可以通过访问一个URL的方式调用这个函数。

  1. $ curl -XGET localhost:8080
  2. Hello, world!

FaaS拥有下面的特点:

  1. FaaS里的应用逻辑单元都可以看作是一个函数,开发人员只关注如何实现这些逻辑,而不用提前考虑性能优化,让工作聚焦在这个函数里,而非应用整体。
  2. FaaS是无状态的,天生满足云原生(Cloud Native App)应用该满足的12因子(12 Factors)中对状态的要求。无状态意味着本地内存、磁盘里的数据无法被后续的操作所使用。大部分的状态需要依赖于外部存储,比如数据库、网络存储等。
  3. FaaS的函数应当可以快速启动执行,并拥有短暂的生命周期。函数在有限的时间里启动并处理任务,并在返回执行结果后终止。如果它执行时间超过了某个阈值,也应该被终止。
  4. FaaS函数启动延时受很多因素的干扰。以AWS Lambda为例,如果采用了JS或Python实现了函数,它的启动时间一般不会超过10~100毫秒。但如果是实现在JVM上的函数,当遇到突发的大流量或者调用间隔过长的情况,启动时间会显著变长。
  5. FaaS需要借助于API Gateway将请求的路由和对应的处理函数进行映射,并将响应结果代理返回给调用方。

比如对于一个简单的3层Web应用,在这里后端系统实现了大部分业务逻辑:认证、搜索、事务等,它的架构如下:
云服务类型 - 图3
如果采用Serverless架构,将认证、数据库等采用第三方的服务,从原来的单体后端里分拆出来(可能需要在原来的客户端里加入一些业务逻辑)。对于大部分的任务,通过函数的形式进行执行,而不再使用一直在线的服务器进行支持,如此一来它的架构看起来就清晰多了:
云服务类型 - 图4
这样的拆分除了让各个组件(函数)间充分解耦,每个都很好地实现了单一职责原则(SRP, Single Responsibility Principle)以外,它的好处还有:

  • 减少开支

通过购买共享的基础设施,同时减少了花费在运维上的人力成本,最终减少了开支。

  • 减轻负担

不再需要重复造轮子,需要什么功能直接集成调用即可,也无需考虑整体的性能,只专注于业务代码的实现。

  • 易于扩展

云上提供了自动的弹性扩展,用了多少计算资源,就购买多少,完全按需付费。

  • 简化管理

自动化的弹性扩展、减少了打包和部署的复杂度、可以快速推向市场,这些都让管理变得简单高效。

  • 环保计算

即使在云的环境上,仍习惯于购买多余的服务器,最终导致空闲。Serverless杜绝了这种情况。
在Martin Flower的专栏文章Serverless Architectures曾这样定义Serverless架构:
“Serverless architectures refer to applications that significantly depend on third-party services(AKA Backend as a Service or “BaaS”) or on custom code that is run ephmemeral containers (Function as a Service or “FaaS”)”
正如前面提到了FaaS的每个函数都拥有快速启动和短暂生命周期的特性,让容器作为任务函数运行的基本单位,是不是非常适合FaaS的场景?同样,作为最热门的容器编排工具的Kubernetes又该怎样应对FaaS呢?

Kubernetes 与 FaaS

Fission是一款基于Kubernetes的FaaS框架。通过Fission可以轻而易举地将函数发布成HTTP服务。它通过读取用户的源代码,抽象出容器镜像并执行。同时它帮助减轻了Kubernetes的学习负担,开发者无需了解太多K8s也可以搭建出实用的服务。Fission目前主要支持NodeJS和Python,预支持C# .NET,对Golang的支持也在进行中。Fission可以与HTTP路由、Kubernetes Events和其他的事件触发器结合,所有这些函数都只有在运行的时候才会消耗CPU和内存。
Kubernetes提供了强大的弹性编排系统,并且拥有易于理解的后端API和不断发展壮大的社区。所以Fission将容器编排功能交给了K8s,让自己专注于FaaS的特性。
云服务类型 - 图5
对于FaaS来说,它最重要的两个特性是将函数转换为服务,同时管理服务的生命周期。有很多办法可以实现这两个特性,但需要考虑一些问题,比如“框架运行在源码级?还是Docker镜像?”,“第一次运行的负载多少能接受”,不同的选择会影响到平台的扩展性、易用性、资源使用以及性能等问题。
为了使Fission足够易用,它选择在源码级工作。用户不再参与镜像构建、推仓库、镜像认证、镜像版本等过程。但源码级的接口不允许用户打包二进制依赖。Fission采用的方式是在镜像内部放置动态的函数加载工具,让用户可以在源码层操作,同时在需要的时候可以定制镜像。这些镜像在Fission里叫做“环境镜像”,它包含了特定语言的运行时、一组常用的依赖和函数的动态加载工具。如果这些依赖已经足够满足需求,就直接使用这个镜像,否则的话需要重新导入依赖并构建镜像。环境镜像是Fission中唯一与语言相关的部分。可以把它看做是框架里其余部分的统一接口。所以Fission可以更加容易扩展(这看起来就像VFS一样)。
FaaS优化了函数运行时的资源使用,它的目标是在运行的时候才消费资源。但在冷启动的时候可能会有些资源使用过载,比如对于用户登录的过程,无论多等几秒都是不可接受的。为了改变这个问题,Fission维持了一个面向任何环境容器池。当有函数进来时,Fission无需启动新容器,直接从池里取一个,将函数拷贝到容器里,执行动态加载,并将请求路由到对应的实例。
云服务类型 - 图6
除了安装在本地的Fission主程序外,Fission-bundle设计为一组微服务构成:

  • Controller: 记录了函数、HTTP路由、事件触发器和环境镜像
  • Pool Manager: 管理环境容器,加载函数到容器,函数实例空闲时杀掉
  • Router: 接受HTTP请求,并路由到对应的函数实例,必要的话从Pool Manager中请求容器实例

在Kubernetes上,这些组件都以Deployment的方式运行,并对外暴露Service。除了这三个Fission特有的组件外,还用了Etcd作为资源和映射的存储,同样也以Deployment的方式启动。Controller支持Fission的API,其他的组件监视controller的更新。Router暴露为K8s里的LoadBalancer或NodePort类型的服务(这取决于K8s集群放在哪里)。
目前,Fission将一个函数映射为一个容器,对于自动扩展为多个实例的特性在后续版本里。以及重用函数Pods来支持多个函数也在计划中(在这种情况下隔离不是必须的)。Fission文档简单介绍了它的工作原理:
“当Router收到外部请求,它先去缓存Cache里查看是否在请求一个已经存在的服务。如果没有,要访问请求映射的服务函数,需要向Pool Manager申请一个容器实例执行函数。Pool Manager拥有一个空闲Pod池。它选择一个Pod,并把函数加载到里面(通过向容器里的Sidecar发送请求实现),并且把Pod的地址返回给Router。Router将外部请求代理转发到该Pod,并将响应结果返回。Pod会被缓存起来以应对后续的请求。如果空闲了几分钟,它就会被杀死”
对于较小的REST API来说,Fission是个很好的选择,通过实现webhooks,可以为Slack或其他服务编写chatbots。
Fission同时还支持根据Kubernetes的Watch机制来出发函数的执行。例如你可以设置一个函数来watch某个命名空间下所有满足某个标签的pod,这个函数将得到序列化的对象和这个上下文的Watch Event类型(added/removed/updated)。又如通过设置事件处理函数可以将它应用于简单的监控,指定当任意一个服务添加到集群时向Slack发送一条消息。当然也有更复杂的应用,例如编写一个watching Kubernetes第三方资源(Third Party Resource)的自定义controller。

在Fission的官网上有个入门的使用示例:

  1. $ cat hello.js
  2. module.exports = function(context, callback) {
  3. callback(200, "Hello, world!\n");
  4. }
  5. # Upload your function code to fission
  6. $ fission function create --name hello --env nodejs --code hello.js
  7. # Map GET /hello to your new function
  8. $ fission route create --method GET --url /hello --function hello
  9. # Run the function. This takes about 100msec the first time.
  10. $ curl http://$FISSION_ROUTER/hello
  11. Hello, world!

如果是第一次运行,需要先准备NodeJS的运行环境:

  1. # Add the stock NodeJS env to your Fission deployment
  2. $ fission env create --name nodejs --image fission/node-env

通过阅读Fission的源码,可以很清晰地看到它的执行过程:

  1. 1. fission env create --name nodejs --image fission/node-env

云服务类型 - 图7

  1. 2. fission function create --name hello --env nodejs --code hello.js

云服务类型 - 图8
同样,由fission主程序执行命令function和子命令create,通过–name参数指定函数名为hello,–env参数确定环境,–code参数确定要执行的函数代码。通过POST向/v1/functions发出请求,携带函数信息的JSON。controller拿到JSON后进行函数资源的存储。首先将拿到UUID,然后写到文件名为该UUID的文件里。接着向ETCD的API发送HTTP请求,在file/name路径下有序存放UUID。最后类似上面env命令,将UUID和序列化后的JSON数据写到ETCD里。

  1. 3. fission route create --method GET --url /hello --function hello

云服务类型 - 图9
fission通过参数–method指定请求所需方法为GET,–url指定API路由为hello,–function指定对应执行的函数为hello。通过POST向/v1/triggers/http发出请求,将路由和函数的映射关系信息发送到controller。controller会在已有的trigger列表里进行重名检查,如果不重复,才会获取UUID并将序列化后的JSON数据写到etcd里。
前面的都是由本地的fission程序完成的。我们已经预先创建了fission-bundle的Deployment和Service。它创建了名为fission的命名空间,并在里面启动4个Deployment,分别是controller, router, poolMgr, etcd,并创建NodePort类型的Service: controller和router,分别监听端口31313和31314。同时创建另一个名为fission-function的命名空间用来运行执行函数的Pod.
router使用Cache维护着一份function到service的映射,同时还有trigger集合(有个goroutine通过controller保持对这个trigger集合的更新),在启动时按照添加trigger里的url和针对对应函数的handler初始化路由。

  1. 4. curl http://$FISSION_ROUTER/hello

当执行该curl时,请求发送至router容器。收到请求后会转发到两个对应的handler。一个是用户定义的面向外部的,一个是内部的。实际上它们执行的是同一个handler。任何handler都会先根据funtion名去Cache里查找对应的service名。如果没有命中,将通过poolmgr为函数创建新的Service,并把记录添加到Cache。然后生成一个反向代理,接收外部请求,然后转发至Kubernetes Service。
云服务类型 - 图10
Poolmgr在创建新的service时,会根据env创建Pod pool(初始大小为3个副本的deployment),然后从中随机选择一个Ready的Pod。接着为此建立对应的Service。
Fission是一个开源项目,由Platform 9和社区进行开发。社区正在努力让Kubernetes上的FaaS更加易用和轻松集成。在未来几个月将添加单元测试、与Git集成、函数监控和日志聚合等特性,同时也会跟其他的Events进行集成,对了,还有为更多的语言创建环境。在今年1月份,Fission发布了alpha版。
三、后记
容器技术的出现改变了软件交付的思维,微服务和Serverless虽然没有减少软件生命周期中的环节,但确实改变了下游软件部署和维护的理念,提高了软件开发人员的效率。FaaS是未来的一种可能的走势,但一定不会是最终的未来。总有一天FaaS又会被其他技术所代替。生活在这个信息爆炸、技术飞速更迭的时代很烦恼也很幸福。这就是我们所在的时代,我们正在亲身经历着未来。