辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

book已读完-前端 Serverless 面向全栈的无服务器架构实战

#serverless

image.png

杨凯 中国工信出版集团

大纲#

  • 综述颠覆性影响、理解 sls 和目前技术的定位关系
  • FaaS 是 Serverless 核心思想的实际应用技术
  • BaaS 是 sls 的另一大分值体系

概述#

#cloudnative 云原生被提到最多的概念就是 serverless 了

sls 的概念、sls 的开发理念、极低的运维成本、大幅下降的服务器费用

举例 github pages,开发者把文件部署为静态站点,分配域名、访问服务。屏蔽了很多细节。

举例 CDN,无需关注细节、节点,全球用户高速访问。

可以认为把计算资源作为服务的方式提供产品,复合 serverless 理念,屏蔽技术细节,对外提供服务。

CNCF 在 2018 年发布了 serverless 白皮书

sls 是指无论在应用的构建还是运行,都不用对服务器进行维护和管理

sls 计算平台应该包含一种或者两种能力 faas baas

接下来介绍,使用场景,优势劣势

faas 的优势:研发效率搞、部署成本低、运维成本低、学习成本低、服务器费用低、部署方案灵活、系统安全性高

劣势:平台学习成本高、调试成本高(运行时在云端,本地调试、日志查询困难)、冷启动、供应商锁定

使用场景:

  • 函数本身无状态,和持久化服务器融合
  • 函数独立工作,彼此大量函数联动计算费用会上升
  • 自动伸缩
  • 事件驱动,http、数据库修改、定时事件等
  • 冷启动要求低的场景

faas 本身不支持 http 协议,所以需要通过 api gateway 对外提供 web api

sls 和服务端技术#

单体应用 - 分层架构,UI 层、业务逻辑层 Business Logic Layer、数据访问层 Data Access Layer

三层架构的基础上,比如 企业应用架构模式、领域驱动设计两本书,进一步区分

  • 应用层
  • 领域层
  • 持久层
  • 基础设施层

还是分层的思路,对代码切分,达到关注点分离 Separation of concerns SOC 的目标。

我能不能抽离 登录、权限判断等逻辑,从而在不同业务之间进行复用

微服务 microservices 架构风格,从分布式架构演变而来。多个独立小型服务进行轻量 、可控的软件研发管理。服务之间通过 RPC 实现相互通信,这样各个服务就可以是哟给你不同的技术栈完成功能。

设计系统的架构受制于组织的沟通结构。康威定律。什么样的组织架构,就设计出什么样的架构。比如小公司,单体应用,规模扩大,新增人员需要重新熟悉整体内容,这是网状结构,彼此都需要同步信息,沟通成本指数级增加。

单体拆分为微服务,只关注自己的业务,屏蔽不必要的信息,降低沟通成本

容器化、云计算、noops- devops 的下一阶段,减少研发人在运维的投入,是一种理念。

sls 和前端技术#

bff,后端服务于前端。在前端和后端之间做胶水层,做信息的聚合和裁剪。一个接口完成多个接口的操作。移出不需要的字段等。

这让接口更加灵活。沟通成本低。减少请求做性能优化、减少数据暴露做安全性

graphQL 在多语言的微服务架构下不容易应用,改造成本太高,目前没有太多跨语言。跨数据库统一实现聚合查询的能力。如果与 serverless 结合才有可能

FaaS 技术#

事件驱动。是一种设计模型。

faas 函数同样是事件驱动,不同的 trigger 触发器作为事件源。比如 http 触发器

函数无状态足够简单。

创建函数。里面有很多技术细节,现在改版多次了已经。

  • 运行时选择
    • 默认的
    • 自定义运行时,这种兼容性最高
    • 自定义容器,比如 GPU 容器
  • 基本信息,名称、区域、触发器事件和 http
  • 代码上传
    • 示例 demo
    • zip 包压缩
    • oss 上传
    • 文件夹上传
  • 规格设计
    • cpu 0.05~16g
    • 内存 128M ~ 32 G
    • 临时硬盘 512M、10G
    • 如果选择容器部署,还可以选择 GPU T4/A10 规格
    • 实例并发度。同时处理多少个请求
    • 超时时间 60s
    • 时区
  • 鉴权认证
    • 签名
    • jwt

2015 年,开源社区出现了 serverless framework,目标是成为 sls 的框架和生态系统,解决供应商锁定的问题。

编写细节忽略

7 函数生命周期#

module.exports.handler = function (request, response, context) {
// code
(async () => {
response.setStatusCode(200);
response.setHeader('content-type', contentType);
response.send(fs.readFileSync(path))

})().catch(err => {

response.setStatusCode(500);
response.setHeader('content-type', 'text/plain');
response.send(err.message);

});
}

8 理解函数运行时#

设计模式 23 种设计模式

消息队列,能解决高并发的问题,也能实现系统解耦。削峰填谷。保证信息按顺序接受。

突然想到 信息触发的方案,站内信、短信、微信推送等。

9 自建简易 FaaS#

要保证各函数的安全性,避免互相打扰,隔离的关键技术是沙箱 Sandbox

  • 使用 docker 隔离
  • 使用进程隔离,不如 docker

使用 master 监听函数调用,启用子进程 child 执行函数。返回的结果通信给主进程。

这里使用 child_process.fork() 启动子进程实现隔离。

如果执行代码可以用 eval/Function 来比较,最佳的方案还是 node 的 new vm.Script(code) 方案

但 vm 也会有风险,举例 this.constructor.construcotr

原型链的设计,所以没有原型链就好了

const sandbox = Object.create(null)
vm.createContext(sandbox)
vm.runInContext(code,sanbox)

但是也不完美,社区中使用 vm2 ,通过 proxy 特性进行封装,更加安全。

因此,运行时使用 vm2 和 child_process.fork 组合使用,可以实现隔离和用户代码执行。

实现 http 协议支持,可以使用 koa 来实现。动态下载函数并执行。。

简易版完成,但还需要考虑吞吐性能、安全稳定、开发效率。

每次执行都会创建 子进程来执行,这个进城的创建和销毁管理是性能开销,高并发时候过多的进城也可能导致崩溃,这就考虑 进程池了。

可以使用 cluster,对 child_process 的进一步抽象封装,用起来更好用。

使用 cluster 和 vm2 配合 koa 就能实现一个方案了。

问了 gpt,
可以考虑 generic-pool:这个模块提供了一个通用的资源池,可以用于管理各种资源,包括进程。你可以使用它来创建一个进程池,从而避免频繁地启动和停止子进程。它提供了灵活的配置选项,允许你自定义池的大小、资源分配策略等。

用户代码如果用了死循环,就无法结束任务了。设定超时时间。 vm/vm2 都有 timeout 比如设置 5000ms

异步调用问题,默认的超时不起作用,可以考虑自行实现计时器

确保稳定性,资源限制。cpu、内存、磁盘的高强度使用。要限制资源,在 Linux 里有 CGroup 限制资源,docker 里也用到了这个能力。

介绍了一堆 CGroup 的概念,略过细节,通过命令就可以限制某个进程最多使用 20% 的 cpu 资源了。有点复杂,gpt 答的挺好

提高效率,内置前端常用服务。

  • 简单的 kv 存储,使用 vm2 实现 get/set

当然,最好还是 redis

BaaS 技术#

backend as a service。

![[Pasted image 20230923233047.png]]

后续提到了 firebase 一展示提供了很多开箱机用的基础服务,比如云数据库、云函数、auth、托管、存储等。

还有崩溃报告、性能监控、test lab、应用分发等功能。

还有拓展类的运营功能

  • 应用内消息 in-app messaging
  • 分析
  • a/b testing
  • cloud messaging 云消息,推送 IM 等
  • remote config 配置中心

国内的 leancloud/bmob 等,整体完整性还有差距。

数据库设计原则部分。

比如 posts 和 comments 两张表查询,会有 select 1+n 的问题,也就是需要先查询 n 条记录找到信息,再查询 n 次对应的数据。sql 中使用 join 就行

举个例子,最近五条评论的内容,所属文章标题。

使用 sql 比较简单。如果提前设计成嵌入的方案就容易。如果已经变成引用的方案了,可能需要保留更多冗余内容。设定一个新集合,最新评论的集合,冗余字段。如果有读写问题,就可以改成缓存,一小时更新一次。这带来的问题是,删除时候需要同步删除多份。

如果使用内嵌,一次查询就可以了,而且查询性能好。对于嵌套的复杂数据就不好了。先把数据聚合再排序,实现也是放入内存中,大量数据可能就不好。

快速介绍了 CDN、对象存储等功能

用户鉴权介绍了 OneID 不流行的趋势,介绍了 OAuth 2.0

最终纳入了 IETF 组织,实现了标准化。

oauth2 里提供了四中授权模式

  • 授权码 auth code,默认
  • 简化模式
  • 密码
  • 客户端凭证

后面三种比较特殊,不用管

OAuth 解决的是授权,不是用户认证,引入了 OIDC - openID Connect

进一步拆分了 id token 和 access token

jwt 是 rfc 7519

对接第三方会比较费劲,就产生了 IDaaS 比如 auth0 网站和 authing 网站

  • 身份认证 账户授权
  • sso single sign in 一个应用登录,多个应用共享
  • 对外提供 oauth2
  • 统一发送邮件、短信重置密码
  • 企业身份登录
  • 两步验证

可以看看,有一些 user/rule/rules/hooks 等

没了。

总结展望#

第二部分比较精彩,其他一般。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。