WRY

Where Are You?
You are on the brave land,
To experience, to remember...

0%

从IaaS到FaaS,看待服务框架的发展

云计算的发展历程

云计算是一种资源的服务模式,该模式可以实现随时随地、便捷按需地从可配置计算资源共享池中获取所需的资源(如网络、服务器、存储、应用及服务),资源能够快速的供应和释放,大大减少了资源管理的开销,你甚至可以再也不用理会那些令人头痛的传统服务供应商了。-- National Institute of Standards and Technology

经典云计算框架包括IaaS、PaaS、SaaS三层服务,从硬件平台支撑、基础环境与服务支持以及应用程序使用三个层次为不同用户提供服务和支持。

IaaS: Infrastructure as a Service 基础设施即服务

这一层主要为基础设施运维人员服务,提供计算、存储、网络及其他基础资源。在这一层上,可以部署和运行操作系统和应用程序在内的任意软件。IaaS主要以虚拟机为最小粒度的资源调度单位,有资源利用率低、调度分发缓慢、软件栈环境难以维护等问题。

PaaS: Platform as a Service 平台即服务

这一层主要为开发人员服务,提供支撑应用所需要的软件运行时环境、相关的工具与服务,如数据库服务、日志服务、监控服务等。在这一层上,应用开发者可以专注于核心业务的开发。这一层是从Iaas的基础上发展而来的,所以也继承了IaaS服务的缺点。

SaaS: Software as a Service 软件即服务

为一般用户服务,提供了一套完整可用的软件系统,让一般用户无需关注细节,只需要通过浏览器或者应用客户端就可以使用部署在云上的应用服务。这也是云计算的最终目标。

在经典云计算框架之下的应用程序架构通常如下图所示:

image-20200527173657092

Docker:容器化管理

从IaaS上搭建PaaS进行管理的方式,受到其自身特性所带来的缺点的严重制约,为普通用户提供虚拟机开发测试学习还可以,但已经不能满足大规模的应用系统的部署和升级需求。不破不立,容器化管理颠覆了传统的云计算架构模式,相比之下有如下特点:

  • 采用进程级的隔离控制,与底层共享操作系统,不需要对硬件设备进行虚拟化,因此性能更强,调度更快,同时还能更好地限制容器所能占用的CPU,内存等资源,最后还能避免容器环境之间的冲突。
  • 可以对容器环境进行定制,满足软件环境的统一,消除了线下和线上环境之间的差异,也消除了不同平台之间的差异。
  • 镜像文件分层管理,同一镜像运行多个容器时,底层文件可以复用,减少了资源占用。
  • 多种网络驱动方式,解决了网络资源的冲突,灵活管理容器网络。
  • 得益于应用镜像仓库的支持,我们可以随意部署常见的服务,例如Mysql、NextCloud、Gitlab等等。

Docker与虚拟机之间的对比

image-20200521101006053

容器的小巧精致带来了管理上突破,让我们可以在毫秒级时间内,完成一个容器的启动和停止。不需要PaaS平台因为虚拟机的启动和停止缓慢而只能提前运行好,以保证服务的低延迟和短暂的服务高峰。按照《福布斯》杂志的统计,在商业和企业数据中心的典型服务器仅提供5%~15%的平均最大处理能力的输出,浪费之大,不可小视。那么容器化的诞生带来了什么?

容器技术的成熟推动了无服务器架构(Serverless)的发展,因为容器对代码和代码运行环境的高度封装,使得服务的运行完全可以由第三方托管调度,也就是使得开发人员只需关注核心业务逻辑,不再需要关注运维等方面的问题。进而衍生出了新的服务模式,BaaS和FaaS。

BaaS:Backend as a Service 后端即服务

通过一个个API调用后端服务或者已经实现好的程序逻辑,这些BaaS通常也会来管理数据,例如:AWS提供RDS服务来代替我们自己部署Mysql。

FaaS:Functions as a Service 函数即服务

函数计算是无服务器计算模式的一种形式,属于Serverless的一个子概念。其本质是一种事件驱动的由消息触发的无状态服务,也就是函数计算中没有数据存储,因此更便于进行弹性部署。

在无服务器架构下,应用程序的架构通常如下图所示

img

以上是云计算的发展历程,从中可以看出,云计算提供的服务不断的被抽象化,同时托管平台承担起了更多的运维责任,让开发人员的更专注于业务逻辑的开发(让开发的门槛也不断降低,对我们来说也算是一个警钟,我现在的编程水平很可能就相当于10年之后10岁孩子的水平)。

服务框架

服务框架的发展

  • PHP时代:内嵌代码的方式执行服务端功能。
  • MVC时代:服务端接到一个请求,经过Router转发到Controller,Controller再调用Model数据库服务,处理完成后,交给View渲染成页面反馈给客户端。代表框架:Django、Laravel
  • RPC时代:定义跨语言的独立接口文件,实现函数的远程调用。代表框架:Thrift,类似跨语言协议:Protocol Buffers
  • Micro-Service时代:整个项目由一堆服务组建而成,每个请求都通过服务之间的相互调用,得到结果。框架的关键点就集中到了监控、权限控制和服务治理上。代表框架:Spring CLoud、Dubbo、Istio、Kite

服务框架的目标

  • 保证项目整体质量(抵抗部分低质量代码对整个项目的影响)
  • 微痛地迭代更新和回滚(让每一次小的改动产生的影响都尽可能的小 & 减少版本升级产生的影响)
  • 让团队之间的协作更加方便(更方便的调用其他团队提供的API,同时做好权限管理)

服务框架的趋势

  • 封装越来越完善,需要关心的点越来越小
  • 开发的门槛降低,但深入优化的成本变高
  • 解藕,同时规范约束越来越强

复杂业务平台需要具备的模块

  • 多维度监控报警模块:Prometheus、Druid
  • 日志采集查询模块:Flume、Logstash、Elasticsearch
  • 服务注册模块:Zookeeper、Etcd、Consul
  • 消息队列模块:Kafaka、NSQ
  • 数据存储模块:Redis、Mysql、MongoDB、Hive
  • 弹性集群管理模块:Kubenetes、自建计算引擎

微服务框架(参考链接

监控报警模块

随着微服务数量的越来越庞大,微服务的监控报警平台就尤为重要。可以帮助我们发现问题,排查问题,了解服务的压力、延迟和错误率等等。此外为了分析故障原因,还需要有日志的采集,存储和查询模块。

img
img

链路跟踪

微服务中,一个请求总是涉及一个或多个微服务的调用,当调用出错的时候,我们需要定位到是哪个微服务导致的错误。类似于代码中打印错误的traceback一样。

preview

网关

微服务数量的膨胀,会暴露出大量的接口,接口的安全性问题就暴露出来了。为了应对权限问题,通常会采用网关的方式,在接入服务之前对请求鉴权。

img

动态扩容

动态扩容为了动态应对服务压力,同时也为了容错。动态扩容一般分两步,部署新实例,将实例注册到负载均衡后面。涉及到服务注册和负载均衡相关的技术。

img

熔断、服务降级、限流、限时

  • 熔断:下游服务挂掉之后,应标记为服务不可用,也就是请求快速失败,避免造成积压。同时,通过定期健康检测的方式判断服务有没有恢复。
  • 服务降级:非核心业务在系统压力负载大的情况下,主动缩容保证核心业务的稳定可靠。
  • 限流:上游服务在请求下游失败或者超时的时候,一般会重试,这就造成了下游的压力更大,造成雪崩。导致下游服务刚恢复就被打挂,俗称在棺材里重复着仰卧起坐。因此需要对上游的请求进行控制,保证下游的压力。
  • 限时:上游请求下游服务时,主动声明等待的最长时间,下游服务在超时时主动抛弃没有返回意义的进程。

从服务框架看函数计算

从上述微服务框架的简单例子来看,函数计算十分适合做底层计算引擎支持。就拿Refunc举例,其在自动化扩容、服务发现方面已经完善;并且得益于函数框架的实现思想,监控报警、链路跟踪,网关的实现也并不算难,都能在框架里找到一个切面,改造Refunc,使其适合微服务的思想。但函数计算也有自己的独特之处,就是无状态,因此使用函数计算的前提是有一个稳健的基础设施服务层,保证数据安全可靠高效地服务于函数计算。

如何对业务进行FaaS改造?

根据滴滴的分享,公司的框架升级都应该从公司现有的情况从发,颠覆性的重新建设,基本是天方夜谭。因此这个问题就十分值得讨论,我们应该如何一步步将原有业务转换到函数计算的框架之上。

  • 首先无状态的业务,例如某些分析引擎,计算引擎,只需根据某些输入,就能得出某些策略的,最适合拆分成函数计算。
  • 对业务逻辑和数据进行拆分,将数据统一交给数据模块管理,在数据模块之上,部署函数计算,对数据管理进行接口封装,这一层还可以实现鉴权、缓存等功能。例如,对MVC的架构进行FaaS改造,就是将Model的业务逻辑封装成函数计算。
  • 对于剩下的复杂业务逻辑,先梳理边界,从边缘业务逐渐拆解到函数计算上。同时做好抵抗风险的能力,例如函数调用不成功,仍然调用原来的业务逻辑。

容器化管理工具--Kubernetes

Kubernetes 是一个跨主机集群的开源的容器调度平台,它可以自动化应用容器的部署、扩展和操作 , 提供以容器为中心的基础架构。

Kubernetes承担了两方面的使命,第一方面是面向容器管理,包括容器的部署、扩展以及路由配置等等。另一方面向集群用户,包括用户认证,授权管理以及资源配额等等。

容器管理

Kubernetes管理容器,实际就是管理各种类型的资源,常见的Kubernetes资源,参考这里

用户管理

用户管理主要为了达成是谁能干什么能不能干的问题,参考这里

此外Kubernetes是一个组件化的项目,简单点理解,Kubernetes就相当于一个满是接口的架子,我们可以定制化各种功能,满足差异化的需求,下面是Kubernetes的架构图。

img

容器化管理UI--Rancher

Rancher其实和本次分享的主题不太相关,但Rancher的使用十分广泛,功能强大。Rancher可以理解是站在Kubernetes的基础上的进一步开发(Rancher也可以基于其他的容器管理工具,例如swarm等),这一点和在Kubernetes上进行函数计算框架的开发有相似之处,所以在这里做一个简单的介绍。

Rancher 简介与Rancher如何实现对集群的控制

Refunc 简介

Refunc 特点

Refunc 是在Kubernetes的基础上开发的函数计算框架,具有以下几个特点:

  • 使用Kubectl或者AWS命令进行操作(门槛略高)。
  • 极速搭建,只要有Kubernetes,就可以一行命令完成Refunc的搭建。
  • 自动缩放容,弹性化部署。
  • 扩展性,可以定制化运行时环境,可以扩展到任何希望使用的语言平台。

Refunc 自定义资源

  • Funcdef:Comes from function defination,定义了函数使用的环境,函数的逻辑代码
  • Xenv:Comes from executable environment,定义了运行时的环境
  • Trigger:函数触发器,可以支持HTTP请求触发函数调用

Refunc 组件

  • refunc-play:Refunc自定义资源控制器
  • nats:通讯层
  • aws-api-gw:aws命令服务端
  • s3:函数存储
image-20200522155218212

Refunc 架构图

Refunc Architecture

Fission 简介

Fission 自定义资源

  • functions 函数定义
  • triggers 触发器
  • environments 运行环境
  • Kubernetes event watches 监视Kubernetes的资源变化

Fission 组件

  • Controller:接受 REST API 请求,管理Fission资源,所有Fission资源都存储在Kubernetes中,因此Fission需要有集群的管理员权限。

Fig.1 Controller

  • Router:trigger和function之间的连接,负责将请求,根据路由分发给function。文档介绍的这个模块是无状态的可以扩展的模块,如何实现可以扩展,还需要继续调研下。

Fig.1 Router

  • Executor:Router在没有找到可用的function的时候,会要求Executor进行调度,Executor部署新的function后,会将Pods的地址返回给Router。Executor目前有两种调度策略: PoolManager 和 NewDeploy.

Fig.1 Executor

  • Function Pod:函数组件,负责从存储中拉取用户函数共享给运行时环境,运行时环境加载用户函数,处理reques请求。 Fig.1 Function Pod

  • Builder Manager:将源码编译成可执行函数。当观察到新的包含编译环境的镜像,会将镜像部署成Deployment资源。观察到新的源代码,Builder Manager会让包含编译器的容器,编译源码并上传。

    Fig.1 Builder Manager

  • Builder Pod:编译组件,和函数池的原理较为相似,Fetcher取得源代码后将源代码共享给编译容器进行编译,并上传到存储组件中。

    Fig.1 Builder Pod

  • StorageSvc:存储组件,将所有上传的源代码持久化到Kubernetes的持久化镜像中,并对Builder Pod和Function Pod提供服务。

    Fig.1 StorageSvc

此外还有可选组件Logger、KubeWatcher、Message Queue Trigger、Timer等

  • Message Queue Trigger 通过消息队列中的消息触发函数计算,同时函数计算可以将消息的处理结果推回到结果队列中去。 通过队列的方式,可以实现任务的的分发和结果收集,可以应用到爬虫等后台任务中去。

    Fig.1 Message Queue Trigger

Istio的微服务治理

Refunc & Fission 使用体验

关于函数计算框架的评价

我觉得可以从如下几个角度评价一个函数框架的优劣

  • 框架本身的健壮性和可扩展性,是否适合日后的拓展开发
  • 函数调用的性能问题:调用延迟,缩放容策略等
  • 路由的高效健壮:路由层负载均衡和稳定性

参考内容