Technology

Chart Type 《大数据经典论文解读》 三驾马车学习 Spark 内存管理及调优 Yarn学习 从Spark部署模式开始讲源码分析 容器狂占内存资源怎么办? 多角度理解一致性 golang io使用及优化模式 Flink学习 c++学习 学习ebpf go设计哲学 ceph学习 学习mesh kvm虚拟化 学习MQ go编译器 学习go 为什么要有堆栈 汇编语言 计算机组成原理 运行时和库 Prometheus client mysql 事务 mysql 事务的隔离级别 mysql 索引 坏味道 学习分布式 学习网络 学习Linux go 内存管理 golang 系统调用与阻塞处理 Goroutine 调度过程 重新认识cpu mosn有的没的 负载均衡泛谈 单元测试的新解读 《Redis核心技术与实现》笔记 《Prometheus监控实战》笔记 Prometheus 告警学习 calico源码分析 对容器云平台的理解 Prometheus 源码分析 并发的成本 基础设施优化 hashicorp raft源码学习 docker 架构 mosn细节 与微服务框架整合 Java动态代理 编程范式 并发通信模型 《网络是怎样连接的》笔记 go channel codereview gc分析 jvm 线程实现 go打包机制 go interface及反射 如何学习Kubernetes 《编译原理之美》笔记——后端部分 《编译原理之美》笔记——前端部分 Pilot MCP协议分析 go gc 内存管理玩法汇总 软件机制 istio流量管理 Pilot源码分析 golang io 学习Spring mosn源码浅析 MOSN简介 《datacenter as a computer》笔记 学习JVM Tomcat源码分析 Linux可观测性 学习存储 学计算 Gotty源码分析 kubernetes operator kaggle泰坦尼克问题实践 kubernetes扩缩容 神经网络模型优化 直觉上理解深度学习 如何学习机器学习 TIDB源码分析 什么是云原生 Alibaba Java诊断工具Arthas TIDB存储——TIKV 《Apache Kafka源码分析》——简介 netty中的线程池 guava cache 源码分析 Springboot 启动过程分析 Spring 创建Bean的年代变迁 Linux内存管理 自定义CNI IPAM 共识算法 spring redis 源码分析 kafka实践 spring kafka 源码分析 Linux进程调度 让kafka支持优先级队列 Codis源码分析 Redis源码分析 C语言学习 《趣谈Linux操作系统》笔记 docker和k8s安全访问机制 jvm crash分析 Prometheus 学习 Kubernetes监控 容器日志采集 Kubernetes 控制器模型 容器狂占资源怎么办? Kubernetes资源调度——scheduler 时序性数据库介绍及对比 influxdb入门 maven的基本概念 《Apache Kafka源码分析》——server Kubernetes类型系统 源码分析体会 《数据结构与算法之美》——算法新解 Kubernetes源码分析——controller mananger Kubernetes源码分析——apiserver Kubernetes源码分析——kubelet Kubernetes介绍 ansible学习 Kubernetes源码分析——从kubectl开始 jib源码分析之Step实现 jib源码分析之细节 线程排队 跨主机容器通信 jib源码分析及应用 为容器选择一个合适的entrypoint kubernetes yaml配置 《持续交付36讲》笔记 mybatis学习 程序猿应该知道的 无锁数据结构和算法 CNI——容器网络是如何打通的 为什么很多业务程序猿觉得数据结构和算法没用? 串一串一致性协议 当我在说PaaS时,我在说什么 《数据结构与算法之美》——数据结构笔记 PouchContainer技术分享体会 harbor学习 用groovy 来动态化你的代码 精简代码的利器——lombok 学习 《深入剖析kubernetes》笔记 编程语言那些事儿 rxjava3——背压 rxjava2——线程切换 spring cloud 初识 《深入拆解java 虚拟机》笔记 《how tomcat works》笔记 hystrix 学习 rxjava1——概念 Redis 学习 TIDB 学习 如何分发计算 Storm 学习 AQS1——论文学习 Unsafe Spark Stream 学习 linux vfs轮廓 《自己动手写docker》笔记 java8 实践 中本聪比特币白皮书 细读 区块链泛谈 比特币 大杂烩 总纲——如何学习分布式系统 hbase 泛谈 forkjoin 泛谈 看不见摸不着的cdn是啥 《jdk8 in action》笔记 程序猿视角看网络 bgp初识 calico学习 AQS——粗略的代码分析 我们能用反射做什么 web 跨域问题 《clean code》笔记 《Elasticsearch权威指南》笔记 mockito简介及源码分析 2017软件开发小结—— 从做功能到做系统 《Apache Kafka源码分析》——clients dns隐藏的一个坑 《mysql技术内幕》笔记 log4j学习 为什么netty比较难懂? 回溯法 apollo client源码分析及看待面向对象设计 学习并发 docker运行java项目的常见问题 OpenTSDB 入门 spring事务小结 分布式事务 javascript应用在哪里 《netty in action》读书笔记 netty对http2协议的解析 ssl证书是什么东西 http那些事 苹果APNs推送框架pushy apple 推送那些事儿 编写java框架的几大利器 java内存模型 java exception Linux IO学习 netty内存管理 测试环境docker化实践 netty在框架中的使用套路 Nginx简单使用 《Linux内核设计的艺术》小结 Go并发机制及语言层工具 Linux网络源代码学习——数据包的发送与接收 《docker源码分析》小结 docker namespace和cgroup Linux网络源代码学习——整体介绍 zookeeper三重奏 数据库的一些知识 Spark 泛谈 链式处理的那些套路 netty回顾 Thrift基本原理与实践(二) Thrift基本原理与实践(一) 回调 异步执行抽象——Executor与Future Docker0.1.0源码分析 java gc Jedis源码分析 深度学习泛谈 Linux网络命令操作 JTA与TCC 换个角度看待设计模式 Scala初识 向Hadoop学习NIO的使用 以新的角度看数据结构 并发控制相关的硬件与内核支持 systemd 简介 quartz 源码分析 基于docker搭建测试环境(二) spring aop 实现原理简述 自己动手写spring(八) 支持AOP 自己动手写spring(七) 类结构设计调整 分析log日志 自己动手写spring(六) 支持FactoryBean 自己动手写spring(九) 总结 自己动手写spring(五) bean的生命周期管理 自己动手写spring(四) 整合xml与注解方式 自己动手写spring(三) 支持注解方式 自己动手写spring(二) 创建一个bean工厂 自己动手写spring(一) 使用digester varnish 简单使用 关于docker image的那点事儿 基于docker搭建测试环境 分布式配置系统 JVM执行 git maven/ant/gradle/make使用 再看tcp kv系统 java nio的多线程扩展 《Concurrency Models》笔记 回头看Spring IOC IntelliJ IDEA使用 Java泛型 vagrant 使用 Go常用的一些库 Python初学 Goroutine 调度模型 虚拟网络 《程序员的自我修养》小结 Kubernetes存储 访问Kubernetes上的Service Kubernetes副本管理 Kubernetes pod 组件 Go基础 JVM类加载 硬币和扑克牌问题 LRU实现 virtualbox 使用 ThreadLocal小结 docker快速入门

Architecture

实时训练 分布式链路追踪 helm tensorflow原理——python层分析 如何学习tensorflow 数据并行——allreduce 数据并行——ps 机器学习中的python调用c 机器学习训练框架概述 embedding的原理及实践 tensornet源码分析 大模型训练 X的生成——特征工程 tvm tensorflow原理——core层分析 模型演变 《深度学习推荐系统实战》笔记 keras 和 Estimator tensorflow分布式训练 分布式训练的一些问题 基于Volcano的弹性训练 图神经网络 pytorch弹性分布式训练 在离线业务混部 RNN pytorch分布式训练 CNN 《动手学深度学习》笔记 pytorch与线性回归 多活 volcano特性源码分析 推理服务 kubebuilder 学习 mpi 学习pytorch client-go学习 tensorflow学习 提高gpu 利用率 GPU与容器的结合 GPU入门 AI云平台 tf-operator源码分析 k8s批处理调度 喜马拉雅容器化实践 Kubernetes 实践 学习rpc BFF 生命周期管理 openkruise学习 可观察性和监控系统 基于Kubernetes选主及应用 《许式伟的架构课》笔记 Kubernetes webhook 发布平台系统设计 k8s水平扩缩容 Scheduler如何给Node打分 Scheduler扩展 controller 组件介绍 openkruise cloneset学习 controller-runtime源码分析 pv与pvc实现 csi学习 client-go源码分析 kubelet 组件分析 调度实践 Pod是如何被创建出来的? 《软件设计之美》笔记 mecha 架构学习 Kubernetes events学习及应用 CRI 资源调度泛谈 业务系统设计原则 grpc学习 元编程 以应用为中心 istio学习 下一代微服务Service Mesh 《实现领域驱动设计》笔记 serverless 泛谈 概率论 《架构整洁之道》笔记 处理复杂性 那些年追过的并发 服务器端编程 网络通信协议 架构大杂烩 如何学习架构 《反应式设计模式》笔记 项目的演化特点 反应式架构摸索 函数式编程的设计模式 服务化 ddd反模式——CRUD的败笔 研发效能平台 重新看面向对象设计 业务系统设计的一些体会 函数式编程 《左耳听风》笔记 业务程序猿眼中的微服务管理 DDD实践——CQRS 项目隔离——案例研究 《编程的本质》笔记 系统故障排查汇总及教训 平台支持类系统的几个点 代码腾挪的艺术 abtest 系统设计汇总 《从0开始学架构》笔记 初级权限系统设计 领域驱动理念入门 现有上传协议分析 移动网络下的文件上传要注意的几个问题 推送系统的几个基本问题 用户登陆 做配置中心要想好的几个基本问题 不同层面的异步 分层那些事儿 性能问题分析 当我在说模板引擎的时候,我在说什么 用户认证问题 资源的分配与回收——池 消息/任务队列


serverless 泛谈

2019年08月31日

简介

一篇讲Serverless 的文章有一个留言:Serverless是在服务网格架构之后进行业务逻辑层的改造。Serverless 的核心理念是按需使用,自动弹性。用户不需要容量规划

Serverless 躁动背后的 5 大落地之痛建议细读。

拥抱开放,Serverless 时代的下一征程

为什么Serverless 会火

从用户视角看:托管node ==> 托管pod ==> 托管function。从实践上也是必须这样慢慢推进的,比如一家公司不用云厂商的对象存储、数据库,然后突然一步托管到function 是不可能的。Serverless 时代下微服务应用全托管解决方案微服务化给运维带来了很大的挑战:

  1. 效率:随着应用规模的扩张,新的研发团队需要面临很多开发和测试中的复杂性问题。在团队协作上,不同应用团队之间如何更好地形成稳定的调用链路,在几十,几百甚至上千个应用的大规模场景里如何进行调用链路上应用的快速部署和灰度。此外,如此多应用的流量的处理、调用链路的跟踪和服务鉴权也非常影响效率。
  2. 稳定:微服务化之后,会出现调用链路上某核心应用出现问题,导致整体系统发生雪崩,而且有时缺少可视化、可观测性的系统来帮助快速定位分析问题,导致难以快速定位到出现问题的应用,造成长时间的损失;
  3. 成本:单体应用一般只需部署几台机器;到了微服务时代,随着应用数的剧增,出于可用性的考虑需要为每个应用保持一些冗余,比如一次大促中,一个调用链路会涉及到十几个应用,为了稳定性以及调用链路的安全,会进行整个链路应用的扩容,而实际上很多应用可能长时间没有流量,服务器空闲,导致巨大的成本浪费。 面对微服务带来的这些问题和需求, Serverless 应用引擎在这方面都做了哪些工作? 带来哪些改变?PS:或者说,这些问题如果能得到比较妥善的解决,其实不用Serverless 也可以。

《Serverless入门课》

为什么阿里会上升到整个集团的高度来推进 Serverless 研发模式升级,对此,杜欢表示:“ 这件事本身好像是一件技术的事情,但其实它背后就是钱的事情,都是跟钱相关的。”

为什么阿里巴巴、腾讯这样的公司都在关注 ServerlessServerless 既可以满足资源最大化利用的需求,也能够调优行业内的开发岗位分层结构。

  1. Serverless 可以有效降低企业中中长尾应用的运营成本。中长尾应用就是那些每天大部分时间都没有流量或者有很少流量的应用。尤其是企业在落地微服务架构后,一些边缘的微服务被调用的概率其实很低。而这个时候,我们往往又很难通过人工来控制中长尾应用,因为这里面不少应用还是被强依赖的,不可以直接下线处理。Serverless 之前,这些中长尾应用至少要独占 1 台虚拟机;现在有了 Serverless 的极速冷启动特性,企业就可以节省这部分开销。PS:核心系统可能因为极致追求性能等 还是会“重型”开发,但对于小需求 确实可以用Serverless 来支撑。
  2. 其次,Serverless 可以提高研发效能。现有的研发形态并不能最大化地发挥部分工作岗位的价值,这同样是一种浪费。以导购类型的业务为例,开发这样一个业务通常需要前端开发工程师和后端开发工程师一起配合,但这两个开发岗位在该业务形态下并不能很好地发挥自己的全部价值。对于后端工程师来说,他在这个业务里要做的事情更多只是把现有的一些服务能力、数据组合在一起,变成一个新的数据提供给前端;而前端开发工程师负责把这个数据在页面上展示出来。这样的工作比较机械化,也没有太大的挑战,并不利于后端工程师的个人成长和岗位价值发挥;但在现有的研发模式下,由于缺乏前后端的连接点,前端工程师又不能去做这些比较简单的后端工作,业务上线也不可能给到前端工程师时间和机会去学习再实践。 Serverless 应用架构中,SFF(Serverless For Frontend)可以让前端同学自行负责数据接口的编排,微服务 BaaS 化则让我们的后端同学更加关注领域设计。可以说,这是一个颠覆性的变化,它能够进一步放大前端工程师的价值

从技术演化看Serverless

Serverless 的喧哗与骚动(一):Serverless 行业发展简史

  1. 单机时代,操作系统管理了硬件资源,贴着资源层,高级语言让程序员描述业务,贴着业务层,编译器 /VM 把高级语言翻译成机器码,交给操作系统;
  2. 今天的云时代,资源的单位不再是 CPU、内存、硬盘了,而是容器、分布式队列、分布式缓存、分布式文件系统。就像从汇编语言发展到高级语言后,开发者不用再去关注寄存器、信号、中断等与机器底层相关的细节

今天我们把应用程序往云上搬的时候(a.k.a Cloud Native),往往都会做两件事情:

  1. 把巨型应用拆小,微服务化;
  2. 摇身一变成为 yaml 工程师,写很多 yaml 文件来管理云上的资源。

这里存在两个巨大的 gap,这两个 gap 在图中用灰色的框表示了:

  1. 编程语言和框架,目前主流的编程语言基本都是假设单机体系架构运行的
  2. 编译器,程序员不应该花大量时间去写 yaml 文件,这些面向资源的 yaml 文件应该是由机器生成的,我称之为云编译器,高级编程语言用来表达业务的领域模型和逻辑,云编译器负责将语言编译成资源描述。

喧哗的背后:Serverless 的概念及挑战Docker 和 Kubernetes,其中前者标准化了应用分发的标准,不论是 Spring Boot 写的应用,还是 NodeJS 写的应用,都以镜像的方式分发;而后者在前者的技术上又定义了应用生命周期的标准,一个应用从启动到上线,到健康检查、下线,有了统一的标准。有了应用分发的标准和生命周期的标准,云就能提供标准化的应用托管服务,包括应用的版本管理、发布、上线后的观测、自愈等。例如对于无状态的应用来说,一个底层物理节点的故障根本就不会影响到研发,因为应用托管服务基于标准化应用生命周期可以自动完成腾挪工作,在故障物理节点上将应用的容器下线,在新的物理节点上启动同等数量的应用容器。在此基础上,由于应用托管服务能够感知到应用运行期的数据,例如业务流量的并发、CPU load、内存占用等,业务就可以配置基于这些指标的伸缩规则,由平台执行这些规则,根据业务流量的实际情况增加或者减少容器数量,这就是最基本的 auto scaling,自动伸缩。这就能够帮助用户避免在业务低峰期限制资源,节省成本,提升运维效率。PS: 应用分发的标准 + 应用生命周期的标准 ==> 标准化的应用托管服务 + 运行数据及流量监控 ==> auto scaling ==> 由平台系统管理机器,而不是由人去管理,这就是一个很朴素的 Serverless 理解

如果我们把目光放到今天云的时代,那么就不能狭义地把 Serverless 仅仅理解成为不用关心服务器。云上的资源除了服务器所包含的基础计算、网络、存储资源之外,还包括各种类别的更上层的资源,例如数据库、缓存、消息等等。我们今天主流的使用云的方式不应该是未来我们使用云的方式。我认为 Serverless 的愿景应该是 Write locally, compile to the cloud,即代码只关心业务逻辑,由工具和云去管理资源。PS:这时候就又提到sql,代码就如同sql 只负责表达业务(描述做什么)而不关心怎么做。

云原生运行时的下一个五年:函数是不是下一站? 非常不错。

从 Docker 讲起,深度揭秘阿里云 Serverless Kubernetes无论是 k8s 还是 ServiceMesh,都在分别尝试将服务管理和流量管理下沉到基础设施中。但这些组件本身也存在管理成本,所以演化出云上托管。用户从云平台获取一个 kubeconfig 文件便可以直接通过 kubectl 命令行或者 Restful API 管理集群。再进一步,如果集群里面运行任务大部分都是 long run 并且资源需求是固定的任务,使用 ACK 没有问题,但如果是大量 job 类型的任务或者存在突发流量的情况,ACK 这种临时扩容虚拟机在虚拟机上启用容器方案在弹性方面有所欠缺。那么,有没有一种既能兼容 Kubernetes 使用方式,又能够秒级启动 Pod,并且按照 Pod 维度计费(ACK 按照 Node 维度计费)的方案呢?

Serverfull vs Serverless

Serverfull 就是服务端运维全由我们自己负责,Serverless 则是服务端运维较少由我们自己负责,大多数的运维工作交给自动化工具负责。

  1. 农耕时代,发布+看日志等工具化
  2. 工业时代,资源优化和扩缩容方案也可以利用性能监控 + 流量估算解决;代码自动化发布的流水线:代码扫描 - 测试 - 灰度验证 - 上线。

免运维 NoOps 并不是说服务端运维就不存在了,而是通过全知全能的服务,覆盖研发部署需要的所有需求,让研发同学对运维的感知越来越少。另外,NoOps 是理想状态,因为我们只能无限逼近 NoOps,所以这个单词是 less,不可能是 ServerLeast 或者 ServerZero。

  1. 狭义 Serverless(最常见)= Serverless computing 架构 = FaaS 架构 = Trigger(事件驱动)+ FaaS(函数即服务)+ BaaS(后端即服务,持久化或第三方服务)= FaaS + BaaS
  2. 广义 Serverless = 服务端免运维 = 具备 Serverless 特性的云服务

喧哗的背后:Serverless 的概念及挑战虽然说是 Serverless,但 Server(服务器)是不可能真正消失的,Serverless 里这个 less 更确切的说是开发不用关心的意思。这就好比现代编程语言 Java 和 Python,开发就不用手工分配和释放内存了,但内存还在哪里,只不过交给垃圾收集器管理了。称一个能帮助你管理服务器的平台为 Serverless 平台,就好比称呼 Java 和 Python 为 Memoryless 语言一样。

这里讲下笔者的一个体会,一开始在公司内搞容器化,当时觉得只要把应用以容器的方式跑起来就可以了(应用托管平台)。一开始拿测试环境试验容器化,运维把测试环境的维护工作完全交给 容器团队。这时,天天干的一个活儿是 给web 开发配域名,为此后来针对域名配置定义了一套规范、 开发了一个nginx插件自动化了(引入了网关之后,改为自动更新网关接口)。这个过程其实就是 less 的过程。

从Kubernetes 到Serverless

Knative Serverless 之道:如何 0 运维、低成本实现应用托管?计算、存储和网络这三个核心要素已经被 Kubernetes 层统一了,Kubernetes 已经提供了 Pod 的无服务器支持,而应用层想要用好这个能力其实还有很多事情需要处理。

  1. 弹性:缩容到零;突发流量
  2. 灰度发布:如何实现灰度发布;灰度发布和弹性的关系
  3. 流量管理:灰度发布的时候如何在 v1 和 v2 之间动态调整流量比例;流量管理和弹性是怎样一个关系;当有突发流量的时候如何和弹性配合,做到突发请求不丢失

我们发现虽然基础资源可以动态申请,但是应用如果要做到实时弹性、按需分配和按量付费的能力还是需要有一层编排系统来完成应用和 Kubernetes 的适配。这个适配不单单要负责弹性,还要有能力同时管理流量和灰度发布。

  1. 资源层关注的是资源(如容器)的生命周期管理,以及安全隔离。这里是 Kubernetes 的天下,Firecracker,gVisor 等产品在做轻量级安全沙箱。这一层关注的是如何能够更快地生产资源,以及保证好安全性。
  2. DevOps 层关注的是变更管理、流量调配以及弹性伸缩,还包括基于事件模型和云生态打通。这一层的核心目标是如何把运维这件事情给做没了(NoOps)。虽然所有云厂商都有自己的产品(各种 FaaS),但是我个人比较看好 Knative 这个开源产品,原因有二:

    1. 其模型非常完备;
    2. 其生态发展非常迅速和健康。很有可能未来所有云厂商都要去兼容 Knative 的标准,就像今天所有云厂商都在兼容 Kubernetes 一样。
  3. 框架和运行时层呢,由于个人经验所限,我看的仅仅是 Java 领域,其实核心的还是在解决 Java 应用程序启动慢的问题(GraalVM)。当然框架如何避免 vendor lock-in 也很重要,谁都怕被一家云厂商绑定,怕换个云厂商要改代码,这方面主要是 Spring Cloud Function 在做。

当我们在聊 Serverless 时你应该知道这些

手感/Knative

  物理机时代 Serverless
运行环境 在服务端构建代码的运行环境 FaaS 应用将这一步抽象为函数服务
入口 负载均衡和反向代理 FaaS 应用将这一步抽象为 HTTP 函数触发器
  上传代码和启动应用 FaaS 应用将这一步抽象为函数代码

Knative 作为最流行的应用 Severlesss 编排引擎,其中一个核心能力就是其简洁、高效的应用托管服务。Knative 提供的应用托管服务可以让您免去维护底层资源的烦恼,提升应用的迭代和服务交付效率。

  1. Build构建系统/Tekton:把用户定义的应用构建成容器镜像,面向kubernetes的标准化构建,区别于Dockerfile镜像构建,重点解决kubernetes环境的构建标准化问题。
  2. Serving服务系统:利用Istio的部分功能,来配置应用路由,升级以及弹性伸缩。Serving中包括容器生命周期管理,容器外围对象(service,ingres)生成(恰到好处的把服务实例与访问统一在一起),监控应用请求,自动弹性负载,并且利用Virtual service和destination配置服务访问规则,流量、灰度(版本)和弹性这三者是完美契合在一起的。PS: Service 与普通workload 并无多大区别,结合了istio,你不用为服务配置port 等体现Server的概念

     apiVersion: serving.knative.dev/v1alpha1
     kind: Service
     metadata:
       name: stock-service-example
       namespace: default
     spec:
       template:
         metadata:
           name: stock-service-example-v2
           annotations:
             autoscaling.knative.dev/class: "kpa.autoscaling.knative.dev" # 自动扩缩容
           spec:
             containers:
             - image: registry.cn-hangzhou.aliyuncs.com/knative-sample/rest-api-go:v1
                 env:
                 - name: RESOURCE
                     value: v2
               readinessProbe:
                 httpGet:
                   path: /
                 initialDelaySeconds: 0
                 periodSeconds: 3
       traffic: # 流量管理
       - tag: v1
         revisionName: stock-service-example-v1
         percent: 50
       - tag: v2
         revisionName: stock-service-example-v2
         percent: 50
    
  3. Eventing事件系统:用于自动完成事件的绑定与触发。事件系统与直接调用最大的区别在于响应式设计,它允许运行服务本身不需要屏蔽了调用方与被调用方的关系。从而在业务层面能够实现业务的快速聚合,或许为后续业务编排创新提供事件。PS:这块还感受不到价值

客户端请求通过入口网关转发给Activator(此时pod实例数为0),Activator汇报指标给Autoscaler,Autoscaler创建Deployment进而创建Pod,一旦Pod Ready,Activator会将缓存的客户端请求转发给对应的Pod,网关也会将新的请求直接转发给响应的Pod。当一定周期内没有请求时,Autoscaler会将Pod replicas设置为0,同时网关将后续请求路由到Activator。 PS:可以缩容到0是因为有一个常驻的Activator

与FaaS的关系

Serverless不等价于FaaS。也有人故意划分为Functions Serverless和容器化的Serverless。

FaaS 与应用托管 PaaS(应用托管平台) 平台对比,最大的区别在于资源利用率,这也是 FaaS 最大的创新点。FaaS 的应用实例可以缩容到 0,而应用托管 PaaS 平台则至少要维持 1 台服务器或容器。FaaS 优势背后的关键点是可以极速启动,现在的云服务商,基于不同的语言特性,冷启动平均耗时基本在 100~700 毫秒之间。

为什么 FaaS 可以极速启动,而应用托管平台 PaaS 不行?PaaS 为了适应用户的多样性,必须支持多语言兼容,还要提供传统后台服务,例如 MySQL、Redis。这也意味着,应用托管平台 PaaS 在初始化环境时,有大量依赖和多语言版本需要兼容,而且兼容多种用户的应用代码往往也会增加应用构建过程的时间。所以通常应用托管平台 PaaS 无法抽象出轻量的可复用的层级,只能选择服务器或容器方案,从操作系统层开始构建应用实例。FaaS 设计之初就牺牲了用户的可控性和应用场景,来简化代码模型,并且通过分层结构进一步提升资源的利用率。

关于 FaaS 的 3 层结构,你可以这么想象:容器层就像是 Windows 操作系统;Runtime 就像是 Windows 里面的播放器暴风影音;你的代码就像是放在 U 盘里的电影。

阿里云 FaaS 架构设计与创新实践 未读

其它

Serverless 架构和之前的架构相比,最大的差异是:业务服务不再是固定的常驻进程,而是真正按需启动和关闭的服务实例。

如果基础设施和相关服务不具备实时扩缩容的能力,那么业务整体就不是弹性的。

无服务器已死?这项技术为什么变得人人嫌弃一个良好运行的单体应用或许不应变成一个连接到八个网关、四十个队列和数十个数据库实例的一系列”函数“。因此,无服务器适用于那些尚未开发的领域。几乎没有将现有应用(架构)移植过来的案例。

距离 Java 开发者玩转 Serverless,到底还有多远?

云原生体系下 Serverless 弹性探索与实践 几个收获

  1. 互联网企业往往由于其内部应用具有显著流量特征,应用启动依赖多,速度慢,且对整体资源池容量水位,库存财务管理,离在线混部有组织上的诸多诉求,因而更多的是以容量画像提前弹性扩容为主,基于 Metrics 计算的容量数据作为实时修正,其目标是容量画像足够精准以至于资源利用率达到预期目标。公有云厂商服务于外部客户,提供更为通用,普适的能力,并通过可拓展性满足不同用户的差异化需求。尤其在 Serverless 场景,更强调应用应对突发流量的能力,其目标在于无需容量规划,通过指标监控配合极致弹性能力实现应用资源的近乎按需使用且整个过程服务可用。PS:互联网行业的服务可能秒级启动做不到。
  2. 原地升级给 SAE 带来了诸多价值,其中最重要的是避免重调度,避免 Sidecar 容器(ARMS,SLS,AHAS)重建,使得整个部署耗时从消耗整个 Pod 生命周期到只需要拉取和创建业务容器,于此同时因为无需调度,可以预先在 Node 上缓存新镜像 (PS:镜像push后知道往哪推了),提高弹性效率。SAE 采用阿里开源 Openkruise 项目提供的 Cloneset 作为新的应用负载,借助其提供的原地升级能力,使得整个弹性效率提升 42%。PS:没想到原地升级这么重要
  3. 对于 Java 应用冷启动较慢的痛点,SAE 联合 Dragonwell 11 提供了增强的 AppCDS 启动加速策略,AppCDS 即 Application Class Data Sharing,通过这项技术可以获取应用启动时的 Classlist 并 Dump 其中的共享的类文件,当应用再次启动时可以使用共享文件来启动应用,进而有效减少冷启动耗时