V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zy445566
V2EX  ›  Node.js

虚拟化服务, JS 服务架构的未来

  •  
  •   zy445566 · 2022-11-02 10:13:11 +08:00 · 1968 次点击
    这是一个创建于 751 天前的主题,其中的信息可能已经有所发展或是发生改变。

    由于近两年一直在从事 serverless 系统的开发,本篇文章算是在未来 serverless 开发方向的一些心得,对这套开发模式未来的一些走向提供一些自己的所见所想,也基于目前过于传统的 serverless 的实现在表达不满的同时,自己也重写做了一些实现以及在项目中的一些工程化的实践,得出一些结论和大家共享。当然毕竟一千个人的眼里就有一千个哈姆雷特,所以意见不同请轻喷,感谢。

    序言

    在双逢干涉中,我们有理由怀疑这个世界的真实性。在 docker 诞生后,我们可以虚拟化当前的环境。那么如果实现一个让代码层面就直接实现虚拟化,是不是有点意思?

    虚拟化-核心

    核心作为实现 node.js 虚拟化的第一步,我们要有各种欺骗代码的一些技巧。比如为每块代码都提供出对应的容器,而对于容器而言需要虚拟的部分主要在于虚拟 module 和 process 以及一个重写过的 require 。大致结构如下:

    app.png

    虚拟的 module 的主要作用是打断和宿主 module 的联系,也就是说在虚拟容器中发生的引用可能对于宿主 module 来说根本就没有发生过。

    module.png

    虚拟 process 的目的是让虚拟环境对 process 的修改只对自己生效,而不会影响到宿主环境的 process ,即是环境变量方向的一种欺骗。

    proxy.png

    重写的 require 目的和虚拟 module 的区别主要是实现对系统模块或第三方模块或引用路径的重写或权限限制。比如不允许你引用当前目前外的代码,再比如就是重写 fs 模块,让你读取的文件表明是在服务器而实质是可能是某个分布式数据库中。

    file.png

    源代码传送门: https://github.com/virtual-less/vaas-core

    虚拟化-服务框架

    有了核心,我想是时候跟目前传统的微服务架构和函数即服务再见了,首先我们要有更加优雅的实现。

    • 是时候跟使用仓库隔离来防止引用说再见了👋 我们可以直接在引用层拦截 ✅
    • 是时候跟 callback 和 ctx.body={...}这种丑陋的写法说再见了👋 我们直接用 return 返回数据,throw 抛出异常✅
    • 是时候跟中心化路由这种集中化配置导致易发冲突的方式说再见了👋 我们直接用装饰器的中心化路由实现 [具体如下个例子] ✅
    import {VaasServerType, Decorator } from 'vaas-framework'
    export default class Hello {
        @Decorator.VassServer({type:'http',method:'get',routerName:'/hello'})
        async hello({req,res}:VaasServerType.HttpParams) {
            return {
                hello:'world'
            }
        }
    }
    

    以上是虚拟化服务框架中最简单的代码例子,这里代表了在 /hello/hello 中能返回{hello:'world'}的结果。其中:

    • 每一个变量有拥有其变量提示
    • 路由通过装饰器 VassServer 来配置,同时支持另外两种类型 rpc 和 websocket
    • 通过 return 返回数据,通过 throw 来抛出 Error 类型异常

    既然作为使用虚拟化框架,也就意味着不同的 APP 不能相互实现阻塞和相互的影响,所以在架构实现上对于每个 App 都支持配置多线程数量,且每个多线程中使用 vm 进行对应的虚拟化工作。同时依托于线程池控制,即可实现多个请求复用 worker 。而每个 App 的代码非常巧妙在 worker 中进行了缓存且被不断的使用,直到长期无请求导致 worker 过期回收。具体架构如下:

    vass-framework.png

    这个架构之下还有一个好处就是不需要过度关心内存泄漏问题,因为单次请求结束且超时时间外没有新连接则默认释放内存,这个模式类似 PHP ,但是和 PHP 不同点为不会马上释放,且可以复用多线程的模式。

    如果想要体验,可以使用 npm 的初始化脚本进行体验(系统需要支持 git 且需要在命令行中翻墙,win 系统请谨慎尝试)

    npm init vaas
    

    源代码传送门: https://github.com/virtual-less/vaas-framework

    虚拟化-服务平台

    光有框架,我觉得还是远远不够的,所以我决定使用框架作为底层提供出一个为私有企业定制的一套部署平台,也就是说你可以直接在这个平台上部署一些虚拟化的 App ,同时可以支持直接在平台上实现 App 相关的配置。也就是说这个服务平台的作用是当框架开发完成若干 APP ,可以直接使用这个平台来管理 APP 并实现动态部署,让开发和发布更加简单。同时这个平台也是基于虚拟化-服务框架进行开发的一个 APP 。

    目前服务平台使用了 ETCD 作为配置中心来实现 APP 配置和部署配置。并实现了配置界面:

    App 配置主要用于限制对代码的一些权限配置和性能限制,比如不希望代码读文件则可以不添加 fs 模块权限。如下:

    appConfig.png

    域名配置主要用于当我们需要域名直接打到 app 时做的一些域名上的配置,这样访问就不需要还带有 app 路径。如下:

    hostConfig.png

    在使用 ETCD 作为平台配置组件时,中间发生了一个小插曲,在使用 ETCD 的时候搜索了一圈居然没有支持 ETCD3.5 以上的 npm 包😂,所以顺手简单整合封装了一波。

    源代码传送门: https://github.com/zy445566/netcd

    同时使用 S3 文件服务的完全实现 minio 来作为代码文件服务的管理,包括我们需要发布一些 APP 也是执行vaas deploy 命令先上传到 minio 的服务上,并修改 ETCD 配置来完成部署。再由平台来通过校验本地代码和对比 ETCD 的代码地址区别来决定保证第一时间完成部署。具体架构如下:

    vaas-platform.png

    这个基本是一个最简化的 serverless 部署平台,实现了前后端,对于想要自己定制的,下面也开放的源码,按照自己企业要求修改即可。

    源代码传送门:

    后端: https://github.com/virtual-less/vaas-platform

    前端: https://github.com/virtual-less/vaas-platform-ui

    结语

    通过底层的虚拟化,开发层面上框架层,到最后使用层面的平台层,严格来说这其实是代码层面上的 serverless 的开源实现。但是比目前 serveless 平台来比较的话,更关注于个人或企业内部的使用,而不是对外开放使用。同时在代码使用方式和开放部署流程上的一些优化与提升。在服务架构上来说未来不一定说一定会朝着虚拟化这个方向前进,但一定会是一个必经之路。

    11 条回复    2022-11-02 16:17:22 +08:00
    lmshl
        1
    lmshl  
       2022-11-02 11:45:43 +08:00
    我想知道如果我在 handler 中多写几个 new Buffer(2147483647).fill(0) 会怎样?

    其他人的 APP 不会跟着 OOM 炸了么?
    qq316107934
        2
    qq316107934  
       2022-11-02 11:51:26 +08:00
    异步调用在虚拟化 process 终止的时候有办法也随之终止么?
    gabon
        3
    gabon  
       2022-11-02 12:22:54 +08:00 via iPhone
    虽然,但是为什么因为双缝干涉实验会怀疑世界真实性?
    adek06
        4
    adek06  
       2022-11-02 13:45:47 +08:00
    @gabon 观察者影响了实验结果 -> 观察者会导致坍缩 -> 没有观察者就不会导致坍缩 -> 世界是因为观察者的观察才存在 -> 没有观察者就没有世界
    0o0O0o0O0o
        5
    0o0O0o0O0o  
       2022-11-02 14:11:34 +08:00
    只是个偶尔使用 serverless 的用户,不了解 serverless:感觉很像 https://blog.cloudflare.com/workerd-open-source-workers-runtime/ ,但是如果保持这个思路,隔离和安全却很难做到同等的水平,会有大量的工作要做,如 #1 所说,甚至难以实现。
    lmshl
        6
    lmshl  
       2022-11-02 14:40:27 +08:00
    安全性不得不考虑吧,起码得把不同客户的代码分布到不同的虚拟地址空间去。
    但如果真的实现到这个层面了,恭喜你,重新发明了进程。
    zy445566
        7
    zy445566  
    OP
       2022-11-02 14:48:54 +08:00
    @lmshl 不会,线程隔离了
    zy445566
        8
    zy445566  
    OP
       2022-11-02 14:52:35 +08:00
    @qq316107934 这是个问题,看来还是不能直接让 process 调用方法。刚刚测试了下,目前来说因为 APP 有线程隔离,所以只有当前 APP 受影响
    zy445566
        9
    zy445566  
    OP
       2022-11-02 14:54:50 +08:00
    @0o0O0o0O0o 确实,对外使用确实风险挺大,对内还好
    zy445566
        10
    zy445566  
    OP
       2022-11-02 14:56:12 +08:00
    @lmshl
    如果要完全考虑安全性,100 个人也是干不完的。
    嘿嘿,所以我这个定位是内部系统,使用者都是你同事或公司内部
    zy445566
        11
    zy445566  
    OP
       2022-11-02 16:17:22 +08:00
    @0o0O0o0O0o 对于多线程模式和无法绝对安全角度确实有点像,但实际上 vaas 更注重虚拟,cloudflare 的 workerd 更注重多线程
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2338 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 16:00 · PVG 00:00 · LAX 08:00 · JFK 11:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.