首页 > 其他分享 >开源 Serverless 框架 Laf 性能优化实践

开源 Serverless 框架 Laf 性能优化实践

时间:2023-12-14 12:01:01浏览次数:25  
标签:Serverless const 函数 Laf vm 开源 模块 日志

介绍

Laf 是一个完全开源的 Serverless 框架,Laf 的 Node.js 运行时容器 (以下简称为 Runtime) 是 Laf 的函数执行环境,依托于 Express.js 框架。采用容器进程常驻的方式,每一个应用对应于一个或多个容器 (弹性伸缩下),底层使用了 Node.js 的 vm 模块,使用 MongoDB 的 watch() 方法来监听函数变更事件,以实现函数发布和配置发布。

Node.js vm 模块

Node.js 的 vm 模块是一个提供虚拟机功能的模块,用于在 Node.js 环境中创建一个独立的 JavaScript 执行环境。它允许在应用程序中运行和控制一段 JavaScript 代码,同时提供了一些安全性隔离性

这个模块包括一些可用于创建隔离的执行环境的函数,使得代码能够在独立的上下文中运行,防止对主应用程序的影响。这在某些情况下可以提供更高的安全性,例如在沙盒环境中执行用户提供的代码,或者实现一些动态加载执行代码的需求。

原文链接:https://forum.laf.run/d/1146

为什么要优化

目前 Laf 的函数运行时存在以下问题:

  1. 频繁使用 Node.js vm 模块重复创建 vm,vm 创建执行的过程中,CPU 消耗很高。在以下对 runtime 的 CPU 火焰图分析可见,在函数执行过程中,有两部分 CPU 执行时间较长,分别是输出函数请求日志vm 创建执行过程

  1. 有时候遇到复杂的函数嵌套引用的时候,会导致循环引用,内存迟迟无法回收,造成内存泄漏,导致 OOM Killed。
  2. 交由 runtime 自己通过 HTTP 调用的形式,异步请求持久化函数日志,性能损耗大,QPS 直接减半
  3. 函数引擎这块的逻辑越来越复杂和臃肿,维护难度很大,急需重构。

如何优化

在前面的分析中,我们知道,当前造成性能瓶颈的原因主要有两点:

  1. 为了实现隔离,vm 模块重复创建,CPU 消耗高,特别是当函数引用达到一定规模时。另一方面,复杂的引用下,甚至会发生内存难以回收造成内存泄漏的问题。
  2. 频繁打印函数请求日志,依赖单线程的 Node.js 通过异步请求处理 console.log 等日志,导致实际业务请求吞吐量下降。

因此,我们采用以下优化思路:

  1. 日志方面:使用标准输出的形式输出日志,交由 K8s 自己采集日志,而不由 runtime 自己处理。

  2. 函数引擎方面:第一次函数调用时,构建并缓存函数模块,下次调用直接取出使用,不需要重复编译,这块更改需要确保以下因素:

    1. 保证这个缓存的函数模块是无状态,即 y = f(x),输入相同的 x,则必然输出确定的 y。
    2. 函数发布时,要及时清理缓存的函数模块。

优化前后架构对比分析

  • 优化前:

  • 优化后:

优化步骤

  1. 改造日志方案为容器日志标准输出,交由 K8s 收集,完全去除日志的有状态依赖。
  2. 重构函数引擎,建立函数模块,每一个函数模块的导出都是一个 JS 对象,无论是代码还是引用的第三方包,都被视作为一个 Module,在代码中只会存在一份,等同于原生的 require / export:
    1. 简化代码,尽可能复用,保留核心逻辑;
    2. 去除函数模块中的有状态部分;
    3. 在函数执行、函数引入处建立函数模块缓存
  3. 针对调试模式,每次函数执行时重新构建函数模块,主动收集执行日志。

核心函数调用逻辑

const vm = require('vm')

// 函数列表
const functionList = {
    a: "const b = require('b'); const func = () => b(); module.exports = func",
    b: "module.exports = () => 'hello world'"
}

// 函数模块缓存
const functionModuleCache = new Map()

// 构建函数模块
const buildFunctionModule = (name) => {
    // 自定义 require 逻辑,用来加载函数
    const customRequire = (specifier) => {
        if (functionModuleCache.has(specifier)) {
            return functionModuleCache.get(specifier)
        }
        if(functionList[specifier]) {
            return buildFunctionModule(specifier)
        }
        return require(specifier)
    }
    
    // 全局上下文
    const ctx = {
        __require: customRequire,
        module: {
            exports: {},
        }
    }

    // 重新定义 require
    const wrapCode = code => {
        return `
        const require = (name) => {
            return __require(name)
        }

        ${code}
        module.exports;
        `
    }
    
    // 构建模块
    const script = new vm.Script(wrapCode(functionList[name]))
    const mod = script.runInNewContext(ctx)
    // 缓存构建结果
    functionModuleCache.set(name, mod)
    return mod
}

// 简单写一个入口函数
const main = () => {
    const func = buildFunctionModule('a')
    const res = func()
    console.log(res)
}

main()

优化效果

压测

下面以 Laf 应用最低配置 0.1c 128m 为例进行压测。

  1. 常规 HTTP 请求:

    数据量 测试结果 QPS
    10 并发请求 1000 次 110
    100 并发请求 1000 次 122
  2. WebSocket 连接

    每秒创建 100 个 websocket 连接,当创建 1 万个 websocket 连接时,资源占用情况如下:

真实案例

某个跑在 laf 上的应用,日活数十万,原来需要 4 个 G 的内存,优化后,内存降至 512 MB 以下,CPU 只需要不到 1 核

附加彩蛋

除此之外,我们还做了不少额外的工作:

  1. 日志支持根据不同 Level,以不同的颜色输出。
  2. 通过重定向自定义依赖安装路径,现在支持安装和内置依赖版本不同的依赖包。
  3. 拦截器现在支持类似 koa 洋葱圈结构的前拦截和后拦截的写法,详情查看 Laf 文档。
  4. ...

总结

通过优化 Laf 运行时,我们在将每个应用的成本降低至原来的 1/10 的同时,还大大提高了性能和稳定性,成功把 Laf 的价格打了下来 ~

标签:Serverless,const,函数,Laf,vm,开源,模块,日志
From: https://www.cnblogs.com/ryanyangcs/p/17900920.html

相关文章

  • 【开源】贪吃蛇小游戏
    #include<bits/stdc++.h>//清屏:system("cls"); 1:'◎'2:'⊙'3:'▲'4:'◆'5:'■'#include<windows.h>//停顿:Sleep();#include<conio.h>usingnamespacestd;inta[100][100],dir[100......
  • 最强Pose模型RTMO开源 | 基于YOLO架构再设计,9MB+9ms性能完爆YOLO-Pose
    https://mp.weixin.qq.com/s/4EJAKBcqlCzDXib1_TKJxw点击下方卡片,关注「AI视界引擎」公众号AI视界引擎「AI视界引擎」公众号不仅致力于分享AI视觉与大语言模型的前沿科技,还将成为连接业界专家、学术界和广大读者的桥梁。我们将提供最新的研究进展、技术突破、应用案例以......
  • 03 开源任务管理系统:创建一个任务
    GitHub地址:https://github.com/dom-bro/task-manager虽说是一个任务管理系统,但简单地讲,其实就是任务的增删改查(CRUD)。其中最重要的又当属增,即创建任务,此为数据之源,删改查都依赖于它所产生的数据。交互设计凭着程序员的直觉,最初做成了一个表单如下图,表单项也对应了数据库......
  • 夜莺开源版对H3C交换机设备监控(一)
    夜莺单机版部署就使用官方推荐的二进制部署:最推荐的方式,稳,升级也方便,使用系统为CentOS7.9。安装前置依赖#夜莺架构依赖MySQLyum-yinstallmariadb*systemctlenablemariadbsystemctlrestartmariadbmysql-e"SETPASSWORDFOR'root'@'localhost'=PASSWORD('1234');"......
  • 开源机器学习版本的Github:Hugging Face
    参考:https://baijiahao.baidu.com/s?id=1776478347325976510https://zhuanlan.zhihu.com/p/535100411 ===============================   ......
  • 42K+ star!开源Notion 平替笔记推荐
    IT咖啡馆,探索无限可能!恭喜你发现了这个宝藏,这里你会发现优质的开源项目、IT知识和有趣的内容。今天我们来推荐一款在GitHub超过43KStar的开源项目:AppFlowy。提到笔记和知识管理,很多人都会想到大名鼎鼎的Notion,无论是项目管理、笔记整理,还是团队合作,Notion都以直观、灵活的界面满......
  • 开源的linux可视化管理项目-1panel面板
    推荐一款开源的linux可视化管理项目,运维效率翻倍原创 小羊架构 小羊架构 2023-12-0316:19 发表于广东收录于合集#linux3个#开源5个#编程9个#IT16个#互联网17个  你好呀,我是小羊。linux是个非常好的开源操作系统,功能强大,使用也非常广泛,唯一的缺点就是上手有点难......
  • 【开源项目推荐】-支持GPT的智能数据库客户端与报表工具——Chat2DB
    2023年是人工智能爆火的一年,ChatGPT为首的一系列的大模型的出现,让生成式人工智能彻底火了一把。但有人会说,GPT对于我们数据开发来说并没有什么作用啊?今天为大家推荐的开源项目,就是GPT在数据领域的一个优秀实践项目。让我们一起来看看吧~Chat2DB是一个集成了ChatGPT功能的数据库S......
  • Databend 开源周报第 123 期
    Databend是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn。What'sOnInDatabend探索Databend本周新进展,遇到更贴近你心意的Databend。支持统计和显示合并状态Databend现在支持统计和显示ME......
  • C#开源克隆类库DeepCloner的功能、优点与妙用
    在开发过程中有时候我们需要对现有对象进行克隆,我们可以使用DeepCloner类库来完成这个需求功能。DeepCloner类库功能:深度克隆: DeepCloner提供深度克隆对象的能力,递归地克隆对象图中的所有引用类型属性。循环引用处理: 能够处理对象图中的循环引用,防止无限递归。自定义克......