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

2022-11-02 10:13:11 +08:00
 zy445566

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

序言

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

虚拟化-核心

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

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

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

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

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

虚拟化-服务框架

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

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'}的结果。其中:

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

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

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

npm init vaas

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

虚拟化-服务平台

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

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

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

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

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

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

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

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

源代码传送门:

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

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

结语

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

1963 次点击
所在节点    Node.js
11 条回复
lmshl
2022-11-02 11:45:43 +08:00
我想知道如果我在 handler 中多写几个 new Buffer(2147483647).fill(0) 会怎样?

其他人的 APP 不会跟着 OOM 炸了么?
qq316107934
2022-11-02 11:51:26 +08:00
异步调用在虚拟化 process 终止的时候有办法也随之终止么?
gabon
2022-11-02 12:22:54 +08:00
虽然,但是为什么因为双缝干涉实验会怀疑世界真实性?
adek06
2022-11-02 13:45:47 +08:00
@gabon 观察者影响了实验结果 -> 观察者会导致坍缩 -> 没有观察者就不会导致坍缩 -> 世界是因为观察者的观察才存在 -> 没有观察者就没有世界
0o0O0o0O0o
2022-11-02 14:11:34 +08:00
只是个偶尔使用 serverless 的用户,不了解 serverless:感觉很像 https://blog.cloudflare.com/workerd-open-source-workers-runtime/ ,但是如果保持这个思路,隔离和安全却很难做到同等的水平,会有大量的工作要做,如 #1 所说,甚至难以实现。
lmshl
2022-11-02 14:40:27 +08:00
安全性不得不考虑吧,起码得把不同客户的代码分布到不同的虚拟地址空间去。
但如果真的实现到这个层面了,恭喜你,重新发明了进程。
zy445566
2022-11-02 14:48:54 +08:00
@lmshl 不会,线程隔离了
zy445566
2022-11-02 14:52:35 +08:00
@qq316107934 这是个问题,看来还是不能直接让 process 调用方法。刚刚测试了下,目前来说因为 APP 有线程隔离,所以只有当前 APP 受影响
zy445566
2022-11-02 14:54:50 +08:00
@0o0O0o0O0o 确实,对外使用确实风险挺大,对内还好
zy445566
2022-11-02 14:56:12 +08:00
@lmshl
如果要完全考虑安全性,100 个人也是干不完的。
嘿嘿,所以我这个定位是内部系统,使用者都是你同事或公司内部
zy445566
2022-11-02 16:17:22 +08:00
@0o0O0o0O0o 对于多线程模式和无法绝对安全角度确实有点像,但实际上 vaas 更注重虚拟,cloudflare 的 workerd 更注重多线程

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/891986

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX