我们开发完一个 Node.js 或 Bun 项目,要部署到线上,pm2 往往是唯一选择。
它是有 Nodejs 实现的进程管理工具,可以让 Node.js 项目持续运行,崩溃重启,是提供线上稳定服务的不二之选。
我从使用 Node.js 开始,就一直用 pm2 来部署我的线上项目,但久而久之,也有点厌倦,久而久之,就萌生了自己写一个 Node.js 进程管理器的想法。
现在,这个想法已经实现了,它采用国产编程语言 MoonBit 实现,叫做bm2,有什么特点呢?其实没啥特点。
什么意思?你没看错,bm2最大的特点,就是没啥特点,且听我一一道来。
首先,bm2只提供了如下几个命令:
start:启动项目kill:关闭项目list:查看项目refresh:刷新bm2版本upgrade:升级项目version:打印版本
一共 6 个命令,比 pm2 的命令少了一大截,所以,我称之为没啥特点。
但有个概念,叫做少即是多,虽然命令更少,功能更少,但它令人更踏实。
因为我们90%的命令,都用不上,甚至从来没用过,一个线上部署工具,最重要的就是稳、狠、准。
bm2就是这样一个致力于用最少的实现,最少的功能,去解决最重要的线上部署的长期稳定,可靠运行的问题。
接下来,我分享如何使用bm2。
如图,这是在 linux 服务器上的实战步骤,下面一一道来。
安装 MoonBit
curl-fsSLhttps://cli.moonbitlang.cn/install/unix.sh|bashbm2 是用 MoonBit 实现的,第一步就是先在 linux 服务器上安装 MoonBit。
这里注意一下,bm2 只支持 Linux 系统,当然,MacOS 应该也是支持的,只不过我没有机器测试,欢迎反馈。
因为,线上部署,非 Linux 莫属,没必要让 bm2 在 windows 系统上跑。
重载 bash 环境
source~/.bashrc moonhelpmooonbit 安装好之后,用source ~/.bashrc重新加载一下环境,让moon命令生效。
如果你要问什么是moon?你就这么理解,它就是Node.js里面的npm。
更新索引
moon update# Registry index cloned successfully# Symbols updated successfully接着,运行moon update更新索引。
安装 bm2
mooninstallchensuiyi/bm2/...--bin~/.local/bin# Downloading chensuiyi/bm2@0.2.1# Downloading moonbitlang/x@0.4.41# Downloading moonbitlang/quickcheck@0.14.0# Downloading bobzhang/toml@0.4.2# Downloading bobzhang/lexer@0.2.0# Finished. moon: ran 17 tasks, now up to date# Success: Installed `bm2` to `/root/.local/bin/bm2`# Finished. moon: ran 3 tasks, now up to date# Success: Installed `bm2d` to `/root/.local/bin/bm2d`接着,用如上命令,安装bm2,通过--bin参数,安装后直接放到~/.local/bin目录下。
这是我非常喜欢 MoonBit 的一个点,从语言层面提供了命令的下载到安装闭环!
接着,会看到Downloading、Finished、Succes,就表示安装成功了。
把 bm2 加入到环境变量
echo'export PATH="$HOME/.local/bin:$PATH"'>>~/.bashrcsource~/.bashrc问题来了,光下载还不顶用,moon 命令还是找不到呀,因为~/.local/bin目录不在我们的环境变量里。
所以,我们需要运行如上2个命令,把~/.local/bin加入到环境变量重,并重载.bashrc配置。
当然,如果一开始就指定把bm2放到诸如/usr/bin,/usr/local/bin之类的,就能直接用起来啦。
[root@tsy7822 ~]# bm2 listno instances接着,运行bm2 list,会提示no instances无实例,因为我们还没运行项目呢。
运行项目
[root@tsy7822 /www/wwwroot/xxx]# bm2 startstarted NAME ID PID PORT STATUS RESTARTS MEMORY UPTIME CWD api025994313002online053MB 0s /www/wwwroot/xxx api125994323003online053MB 0s /www/wwwroot/xxx api225994343004online053MB 0s /www/wwwroot/xxx api325994363005online053MB 0s /www/wwwroot/xxx所以,我们进入到Node.js或Bun项目,运行bm2 start,就能看到项目运行起来啦。
bm2 配置
保险起见,可不是任何项目都能直接运行的,必须要对项目提供一个bm2.toml配置文件。
name = "api" # 项目代号,唯一,字幕,数字,下划线 cwd = "/srv/api" # 项目路径 script = "src/index.js" # 项目入口 instances = 2 # 实例数量 port = 3000 # 监听端口 [env] API_HOST = "https://abc.com/" MYSQL_HOST = "127.0.0.1" MYSQL_PORT = "5566"这是一个基本的项目配置。
| 字段 | 含义 |
|---|---|
name | 项目/应用名。字母开头,后接字母、数字和下划线;在所有已注册项目中唯一。 |
script | cwd内的相对脚本路径;禁止..。 |
instances | 实例数量;1..1024。 |
port | 第一个实例的端口;后续实例使用连续端口。 |
可选字段(含默认值):
| 字段 | 默认值 | 含义 |
|---|---|---|
cwd | 配置目录 | 应用工作目录(绝对路径)。 |
runtime | bun | 运行时可执行文件:bun或node。 |
max_memory_mb | 512 | 最大 VmRSS(MiB);至少为1。 |
max_restarts | 10 | 允许的连续异常重启次数;0表示禁用重试。 |
restart_delay_ms | 1000 | 自动重启前的延迟。 |
min_uptime_ms | 10000 | 早于该时长的干净退出会计入重启预算。 |
stop_timeout_ms | 10000 | SIGTERM 到 SIGKILL 之间的宽限期;最大60000。 |
完整的配置如上。
环境变量
环境变量
bm2 只把自己的PATH、HOME、TMPDIR传给被管理进程,外加这些保留变量:
BM2_APP_NAMEBM2_INSTANCE_IDBM2_APP_INSTANCE(实例编号,第一个实例为"0";与 PM2 的NODE_APP_INSTANCE约定一致,便于集群感知的应用选择主实例)BM2_APP_PORT(分配给该实例的端口)NODE_ENV(恒为"production":bm2 是生产运行工具,被管理应用可以可靠地检测到自己在 bm2 之下)
Bun 会自动从项目的cwd加载.env文件。
bm2 保留变量优先于[env]和.env中的值。
环境变量名必须使用字母、数字和下划线,不能以数字开头,且上述保留名加PATH/HOME/TMPDIR会被拒绝。
nginx & caddy 负载均衡
设置了bm2.toml配置,并成功运行项目后,bm2会基于port端口 和instances实例数量,创建多个进程fork。
[root@tsy7822 /www/wwwroot/xxx]# bm2 startstarted NAME ID PID PORT STATUS RESTARTS MEMORY UPTIME CWD api025994313002online053MB 0s /www/wwwroot/xxx api125994323003online053MB 0s /www/wwwroot/xxx api225994343004online053MB 0s /www/wwwroot/xxx api325994363005online053MB 0s /www/wwwroot/xxx所以你就会看到这样的多个实例,是互相独立,互不影响的,要让不同的实例承担共同的访问流量,就要对Nginx或Caddy这样的 Web 服务托管工具进行负载均衡的配置,把请求平均分配到不同的实例上面。
upstream api_backend{server127.0.0.1:3002;server127.0.0.1:3003;server127.0.0.1:3004;server127.0.0.1:3005;}Nginx 配置如上。
xxx.com{# 多个上游 = 自动轮询负载均衡reverse_proxy127.0.0.1:3002127.0.0.1:3003127.0.0.1:3004127.0.0.1:3005}Caddy 配置如上。
当然,最后都要重启 Nginx 或 Caddy,你的线上服务就平稳运行啦。
bm2是一个正在开发中的项目,欢迎大家积极反馈,不断完善。
开源地址:https://github.com/chenbimo/bm2