简介: 函数即服务(FaaS)作为云计算 2.0 时代重要的倒退方向,可能从工程效率、可靠性、性能、老本等方面给开发者带来微小的价值,尤其是可能极大地晋升研发效率。因而,拥抱 FaaS 成为开发者关怀的重要技术畛域。阿里娱乐技术专家墨洵、研发工程师武升将介绍娱乐函数计算平台的设计思维与关键技术难点,并联合业务介绍函数计算的落地实践经验。
一 背景
优酷内容散发业务涵盖了优酷主客的首页、频道页、二级页等不同场景下的内容散发,服务端之前采纳传统的 Java 利用联合阿里团体中间件的开发模式,始终是产品评审、API 设计、前后端联调、前后端发版等节奏。然而,随着端上内容的多样化,产品需要迭代的减速,传统的服务端架构开发模式已显得力不从心,咱们尽管积淀出一套通用框架,但受限于开发模式的实质并没有变动,业务开发的灵活性与开发成本仍然很高。总结起来,面临的挑战次要是:API 依赖数据源多,业务需要变动快,前后端联调老本大等。
随着 Serverless 技术的倒退,FaaS 的相干实际摸索都在阿里外部逐步多起来,咱们思考了 FaaS 的特点和面临的挑战,心愿通过 FaaS 技术的引入,把一系列根底能力积淀下来,在此之上,通过 FaaS 来承接下层业务逻辑,阿里巴巴娱乐优酷 FaaS 平台应运而生。
二 平台设计与技术难点
1 设计指标
心愿实现一个通用的函数计算平台,在这个平台上,开发者间接通过编写、运行和治理一个或多个函数对外提供服务,容许通过微服务、HTTP 接口、事件源触发等多种形式调用函数。同时,函数的开发及公布应该是秒级失效,且无需重启宿主利用的,这样就能够克服传统 Java 利用公布部署的工夫老本,极大的加重开发者在代码开发之外的工夫老本,同时能够疾速回滚。
FaaS 平台应该提供函数式利用的运行环境,应该反对轻量级脚本语言编写函数。咱们首选 Groovy 语言,次要是思考了 Groovy 的代码简洁,同时能够拜访 Java 的原生的类和对象。
FaaS 能够依据理论的拜访状况进行函数实例的动静加载和资源分配。
总结起来,在 FaaS 平台上运行的函数应该是一个短小、离散、可复用的代码块,咱们心愿它有以下几个特点:
- 生命周期短,反对疾速公布部署
- 非守护过程(不须要长时间运行,按需加载)
- 不提供长连贯服务
- 无状态
- 可重用现有服务或第三方资源(重点,FaaS 应该建设在欠缺的根底服务上)
- 毫秒级执行工夫
2 平台整体设计
FaaS 平台的整体外围架构次要由网关、运行时容器、一站式运维公布平台、根底服务等组成:
网关层次要负责承受函数调用申请,通过函数的惟一标识及函数的集群信息散发函数调用到对应集群的机器环境中执行。
函数容器层是整个零碎的外围,次要通过函数执行引擎进行实例的调用执行,同时负责函数实例的生命周期治理,包含按需加载、代码预热、实例卸载回收等工作。
一站式公布运维平台(FaaS Platform)是面向开发者的次要操作平台,开发者在平台上进行函数编写、版本提交公布、回滚、监控运维等一系列工作。整个监控体系买通了团体的根底服务监控体系,, 能够提供实时大盘,集群性能等根本监控指标的查问性能。
整个 FaaS 平台建设在团体中间件以及优酷内容散发依赖的各根底服务之上,通过良好的封装向开发者提供简洁的服务调用形式,同时函数自身的执行都是运行在相互隔离的环境中,通过对立的函数实例治理,进行函数的调度、执行监控、动静治理等。
整体技术栈服务端容器层次要是采纳 Java 实现,联合团体中间件实现整个容器层的次要性能。
前端次要基于 React 框架和 Dva 状态治理框架实现。当然,在理论开发过程中咱们抉择了蚂蚁金服的 Bigfish 框架和 Odin 脚手架。React 提供了组件化的概念,这意味着咱们开发的组件能够像 HTML 根本 DOM 元素一样一直被复用。为了实现组件的复用化和研发效率的晋升,Bigfish 在 Web 页面上进行了分层设计,细粒度从大到小顺次为:页面模板 -> 区块 -> 业务组件 -> 组件。Odin 脚手架是优酷推出一款面向中后盾业务零碎的前端开发脚手架,集成了 Bigfish 的框架,反对以配置化的形式构建网站路由,使得开发者不须要关注过多底层细节,能够疾速上手实现业务逻辑和页面构建。
相似于服务端侧的 MVC 分层模式,前端在实现业务逻辑和数据通信时也有对应的封层设计模式,来实现组件的状态治理。经验了从 Flux -> Redux -> Dva 的衍变,状态管理机制对简单业务带来的好处正在不变突出。Dva 的残缺数据流图如下:
State 是负责保留整个利用状态,View 是 React 组件形成的视图层,Action 是形容事件的对象。connect 办法是绑定 State 到 View 的函数,使得 View 层的组件能够动静监听 State 中的属性,同时能够通过 dispatch 办法负责将 Action 发送至 State 触发状态扭转。触发状态扭转有两种类型的函数:effect 函数和 reducer 函数。前者会与服务端进行数据通信,能够解决异步动作;后者解决同步动作,并间接更新 State。
FaaS Platform 前端次要分为函数创立、函数治理、函数公布、函数模板和利用统计五个模块。在 FaaS Platform 零碎中,函数是对外可被调度的最小单元,而利用是划分机器资源的最小单位,所以咱们设定利用与函数存在一对多的映射关系。
函数创立模块
函数创立模块次要提供增加函数的性能。一个残缺函数必须包含函数名称、函数标识、函数类型、函数所属利用及利用下所属分类等根本信息;同时相似于 mtop 网关,咱们提供对于函数入参、响应业务后果、响应业务错误码的配置页面,用于主动生成函数调用入参表单和函数接口文档。函数的英文标识惟一确定一个函数,不可反复。
函数治理模块
函数治理模块次要提供函数的 CRUD 操作和函数的在线编写性能。在本页面咱们能够疾速进行简单条件的函数查问和函数根本信息和状态的编辑。同时咱们提供函数编写的在线 Web IDE,反对文件增删、代码编写、主动保留、函数提交、函数调试、日志打印等性能。
函数公布模块
函数公布模块次要提供函数提交历史的查问和执行函数公布的性能。咱们像传统 Java 利用反对引入二三方依赖,但不同于传统的 Java 利用公布,FaaS Platform 零碎中的函数公布能够实现秒级公布。目前函数公布曾经反对函数回滚公布和函数分批次公布,从部署环节实现对复杂多变业务需要的疾速响应。
函数模板模块
函数模板模块次要提供函数模板的 CRUD 操作和函数的在线编写性能。结合实际的业务场景,咱们首先提供一些根底的内置模板,不便函数的疾速初始化。同时对于某一个业务问题的残缺解决方案,咱们容许该函数保留为自定义的函数模板。函数模板的 Web IDE 同样反对函数模板的在线编写、调试、主动保留等性能。
利用统计模块
因为函数隶属于利用从而具备机器资源,咱们打算提供利用统计模块以利用为拆分进行函数上线状态、公布版本的数据统计;同时咱们也基于函数日志提供函数调用状况(调用量、成功率、响应工夫)的统计分析和监控。对于具备的细节,咱们正在逐渐实现和欠缺。
3 次要个性
优酷 FaaS 平台的次要个性是开发接入低成本、函数运行时环境隔离以及运维监控操作的透明化。
开发接入低成本
FaaS 平台通过一站式的云端开发平台,使用户能够间接面向业务逻辑的开发,而无需关注根底服务及中间件的依赖,平台自身提供欠缺的根底能力封装,包含:快捷开发能力,中间件疾速接入能力,数据存储疾速接入能力,根底能力封装间接调用等。
业务逻辑开发模式轻量化、无利用化,公布回滚秒级失效,极大的加重了传统服务端开发过程的繁琐流程,将开发者的精力更多的集中于外围业务逻辑的开发。
同时提供如下的简洁易于操作的开发部署流程设计,加重开发者开发部署的工夫老本。
FaaS 平台上的函数除了开发成本低,调用者接入的形式也比较简单。咱们同时提供了中心化和去中心化两种应用形式,不论去中心化还是中心化应用形式,函数代码的编写、调试、公布均在一站式运维公布平台上实现。在中心化接入形式下,咱们通过对立的函数服务集群提供对外服务,容许调用者通过对立的函数调用接口以 HSF 服务或者 HTTP 接口调用函数,而函数代码的执行齐全在咱们的函数服务集群上,开发者无需本人申请利用。
对于去中心化接入形式,开发者如果想调用函数平台上的 FaaS 函数,能够引入咱们提供的 SDK,此时,函数的执行齐全在调用者利用的本地过程里,FaaS 平台只提供函数的开发公布性能。
运行时环境的隔离
运行时环境的隔离分为两个档次,一个档次是函数容器外部函数实例之间的隔离;另外一个档次是不同函数自身就运行在不同的虚构利用集群上,集群与集群之间的隔离性。
函数容器外部函数实例的隔离指的是在 FaaS 平台上编写的 Groovy 函数运行在对立的 JVM 过程中,每个函数在开发的过程中都会生成多个版本,而不同函数之间、同一函数的不同版本之间在运行时的环境都是互相隔离,互不烦扰的。
函数运行集群的隔离性次要是依据函数的访问量、函数的服务特点(长尾服务还是通用服务)等个性,在函数创立之初就将函数绑定在不同的虚构利用上,而不同的利用会运行在不同的机器集群上,函数在被调用时,网关层能够依据函数的利用将函数的调用散发到不同的集群上执行,保障函数之间物理隔离。
运维监控的透明化
FaaS 平台的函数都能在平台上间接进行监控运维操作,咱们通过在函数执行流程上收集函数的执行日志,并将日志实时上报到团体监控服务,能够在平台上实时监控函数运行。
4 技术难点
函数执行引擎设计
函数执行引擎是整个 FaaS 的外围局部,负责函数实例的加载、预热、调度执行、卸载等生命周期治理。FaaS 的函数目前反对 Groovy 语言,抉择 Groovy 次要是因为 JVM 提供的运行时环境人造反对 Groovy 语言的运行。FaaS 平台上每个函数都具备一个本人独立的代码版本库,每次提交都将生成递增的版本,执行引擎加载函数实例时会从版本库中加载以后最新版本的代码,通过初始化、预编译等操作生成函数的实例放到实例池中,因为每个函数都有惟一标识,因而,当调用某个具体的函数时,执行引擎会从实例池中取出对应实例加载执行。整个流程如下图所示:
因为函数实例都存在于同一个 JVM 过程中,并且不同于服务,函数的粒度更小,因而函数的生命周期须要严格控制,不然大量函数加载到内存中,有可能呈现内存占用过大的问题。同时兼顾 SDK 调用形式,避免多个函数常驻内存将宿主利用的内存耗尽。所以目前采纳了懒加载机制,按需加载函数实例到内存中,过期主动回收,有助于开释内存进步内存利用率。
每个 Groovy 函数对应一个 Groovy 的解释器环境 GroovyEngine, 不同的函数之间互相独立,每个函数在加载到内存的过程中都分别独立的进行预编译,初始化等流程,避免不同函数之间互相烦扰,同时为二三方 JAR 包加载提供隔离的环境,防止出现不同函数之间的类加载器相互影响的状况。
二三方 JAR 包加载能力
FaaS 平台提供二三方 JAR 包的加载能力,容许在不重启整个底层容器的状况下,加载函数本人的二三方依赖,咱们通过实现 Groovy 二三方 JAR 包加载能力的 Classloader, 实现了函数与函数之间、函数不同版本之间的二三方依赖加载能力。FaaS 平台的 Classloader 体系:
三 FaaS 平台的落地摸索
联合目前阿里娱乐业务的特点,即大多以内容散发为主,以首页、二级页等业务来看,内容散发具备经营坑位多、需要变动快、数据源多等特点,传统的 Java 服务端开发方式,前后端联调以及后端开发部署都逐步成了影响迭代效率的重要瓶颈,以往都是服务端开发在客户端发版前公布线上,公布耗时长,回滚老本高,因而通过引入 FaaS,心愿进步服务端开发的灵活性,让开发者更多的面向业务逻辑而不是花较大量的工夫在服务的部署保护下面。
优酷外部的内容散发目前次要在对立的内容搭建投放框架之上开发,这套框架是一套流程编排的框架,通过流程编排,从不同数据源获取内容,通过业务逻辑解决,最终通过模版字段映射输入 API 内容。目前 FaaS 次要利用在数据源及模版字段映射阶段。数据源即原始数据接口的封装,通过数据源获取理论业务须要的原始数据,比方媒资节目视频、节目专题数据、用户关注等业务数据;模版字段映射次要通过编写 Java 的函数依据理论业务逻辑生成字段内容。以往的开发模式下,如果业务逻辑有变动,须要变更而后公布 Java 利用能力失效,采纳 FaaS 开发之后,只须要公布对应的 FaaS 函数即可,因为 FaaS 函数的公布是秒级,因而极大的进步了迭代效率。
1 对立的数据源封装
咱们应用 FaaS 实现数据源接口的封装,当有新的数据接口须要接入时,间接在 FaaS 平台上通过编写函数实现,能够做到在本地 Java 利用不公布的状况下,间接上线新数据源。对于新业务接口的疾速接入具备重要意义。同时这些数据源能够被重用,因而在多人合作的模式下,通过复用函数实现的数据源极大的缩小了反复开发量。
2 FaaS 函数解决 API 协定模版字段映射
咱们扩大了搭投框架,通过 Faas 的 SDK,服务端接口的模版解析阶段除了能解析一般的 Java 函数,也能够反对解析 FaaS 函数,这类函数的代码不是通过原生 Java 代码编写,而是在 Faas 平台上用 Groovy 代码编写而成,这类函数的特点是编写、更新、公布均不须要重新部署哥伦布业务利用,只须要在 Faas 平台上操作函数即可。字段逻辑的批改能够齐全不必重启 Java 利用,疾速应答迭代变更。每个函数都有独立的生命周期和公布流程,不同函数的公布变更之间互相隔离。当有字段逻辑的变动时,能够齐全不重启本地 Java 利用,间接通过函数的秒级公布来实现,极大进步了迭代效率。
四 总结与瞻望
目前优酷内容散发相干业务曾经陆续引入 FaaS 能力,在 FaaS 的助力下,迭代效率晋升。然而平台整体上还处于刚刚起步阶段,也是咱们 Serverless 实际的初步尝试。后续咱们心愿在以下几个方面持续摸索 FaaS 平台的技术与落地:
- 反对更多编程语言的运行时环境,以及更敌对的云端 IDE 开发体验。
- 优化函数运行集群的资源调度策略,正当调配函数执行须要的资源,反对动静扩缩容。
- 联合内容散发业务的特点,寻找更多业务的切入点,通过 FaaS 进一步晋升现有技术架构的灵活性和迭代效率。