bm2,不到1M大小实现pm2的nodejsbun线上部署 我们开发完一个 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 服务器上的实战步骤下面一一道来。安装 MoonBitcurl-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更新索引。安装 bm2mooninstallchensuiyi/bm2/...--bin~/.local/bin# Downloading chensuiyi/bm20.2.1# Downloading moonbitlang/x0.4.41# Downloading moonbitlang/quickcheck0.14.0# Downloading bobzhang/toml0.4.2# Downloading bobzhang/lexer0.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 加入到环境变量echoexport PATH$HOME/.local/bin:$PATH~/.bashrcsource~/.bashrc问题来了光下载还不顶用moon 命令还是找不到呀因为~/.local/bin目录不在我们的环境变量里。所以我们需要运行如上2个命令把~/.local/bin加入到环境变量重并重载.bashrc配置。当然如果一开始就指定把bm2放到诸如/usr/bin/usr/local/bin之类的就能直接用起来啦。[roottsy7822 ~]# bm2 listno instances接着运行bm2 list会提示no instances无实例因为我们还没运行项目呢。运行项目[roottsy7822 /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项目/应用名。字母开头后接字母、数字和下划线在所有已注册项目中唯一。scriptcwd内的相对脚本路径禁止..。instances实例数量1..1024。port第一个实例的端口后续实例使用连续端口。可选字段含默认值字段默认值含义cwd配置目录应用工作目录绝对路径。runtimebun运行时可执行文件bun或node。max_memory_mb512最大 VmRSSMiB至少为1。max_restarts10允许的连续异常重启次数0表示禁用重试。restart_delay_ms1000自动重启前的延迟。min_uptime_ms10000早于该时长的干净退出会计入重启预算。stop_timeout_ms10000SIGTERM 到 SIGKILL 之间的宽限期最大60000。完整的配置如上。环境变量环境变量bm2 只把自己的PATH、HOME、TMPDIR传给被管理进程外加这些保留变量BM2_APP_NAMEBM2_INSTANCE_IDBM2_APP_INSTANCE实例编号第一个实例为0与 PM2 的NODE_APP_INSTANCE约定一致便于集群感知的应用选择主实例BM2_APP_PORT分配给该实例的端口NODE_ENV恒为productionbm2 是生产运行工具被管理应用可以可靠地检测到自己在 bm2 之下Bun 会自动从项目的cwd加载.env文件。bm2 保留变量优先于[env]和.env中的值。环境变量名必须使用字母、数字和下划线不能以数字开头且上述保留名加PATH/HOME/TMPDIR会被拒绝。nginx caddy 负载均衡设置了bm2.toml配置并成功运行项目后bm2会基于port端口 和instances实例数量创建多个进程fork。[roottsy7822 /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