Nodejs在虚拟化服务中的角色,JS服务架构的未来
Nodejs在虚拟化服务中的角色,JS服务架构的未来
由于近两年一直在从事 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
虚拟化-服务框架
有了核心,我想是时候跟目前传统的微服务架构和函数即服务再见了,首先我们要有更加优雅的实现。
- 是时候跟使用仓库隔离来防止引用说再见了👋 我们可以直接在引用层拦截 ✅
- 是时候跟 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 过期回收。具体架构如下:
这个架构之下还有一个好处就是不需要过度关心内存泄漏问题,因为单次请求结束且超时时间外没有新连接则默认释放内存,这个模式类似 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 平台来比较的话,更关注于个人或企业内部的使用,而不是对外开放使用。同时在代码使用方式和开放部署流程上的一些优化与提升。在服务架构上来说未来不一定说一定会朝着虚拟化这个方向前进,但一定会是一个必经之路。
我想知道如果我在 handler 中多写几个 new Buffer(2147483647).fill(0) 会怎样?
其他人的 APP 不会跟着 OOM 炸了么?
异步调用在虚拟化 process 终止的时候有办法也随之终止么?
虽然,但是为什么因为双缝干涉实验会怀疑世界真实性?
观察者影响了实验结果 -> 观察者会导致坍缩 -> 没有观察者就不会导致坍缩 -> 世界是因为观察者的观察才存在 -> 没有观察者就没有世界
只是个偶尔使用 serverless 的用户,不了解 serverless:感觉很像 https://blog.cloudflare.com/workerd-open-source-workers-runtime/ ,但是如果保持这个思路,隔离和安全却很难做到同等的水平,会有大量的工作要做,如 #1 所说,甚至难以实现。
安全性不得不考虑吧,起码得把不同客户的代码分布到不同的虚拟地址空间去。
但如果真的实现到这个层面了,恭喜你,重新发明了进程。
不会,线程隔离了
这是个问题,看来还是不能直接让 process 调用方法。刚刚测试了下,目前来说因为 APP 有线程隔离,所以只有当前 APP 受影响
确实,对外使用确实风险挺大,对内还好
如果要完全考虑安全性,100 个人也是干不完的。
嘿嘿,所以我这个定位是内部系统,使用者都是你同事或公司内部
对于多线程模式和无法绝对安全角度确实有点像,但实际上 vaas 更注重虚拟,cloudflare 的 workerd 更注重多线程
Node.js在虚拟化服务中扮演着至关重要的角色,它基于V8引擎,为JavaScript提供了服务器端的运行环境。在虚拟化服务架构中,Node.js的轻量级、高效和非阻塞I/O模型特性,使其能够处理大量并发请求,适用于构建高性能的虚拟化应用程序。
以下是一个简单的Node.js在虚拟化服务中的代码示例,展示了如何创建一个基本的HTTP服务器:
const http = require('http');
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, Virtualization Service!\n');
});
server.listen(3000, '127.0.0.1', () => {
console.log('Server running at http://127.0.0.1:3000/');
});
关于JS服务架构的未来,虚拟化无疑是一个重要的发展方向。通过虚拟化技术,可以实现代码的隔离与资源的优化利用,进一步提升服务架构的灵活性和可扩展性。例如,使用Docker等容器化技术,可以将Node.js应用程序及其依赖项打包到一个独立的容器中,实现应用的快速部署与管理。
总之,Node.js在虚拟化服务中发挥着重要作用,而JS服务架构的未来也将更多地融入虚拟化技术,以提供更高效、灵活和可扩展的服务。