负载均衡
cluster 模式(默认)
toml
exec_mode = "cluster" # 可以省略,默认即 cluster
instances = 4
port = 3000所有实例共享同一个端口。它基于 Linux 的 SO_REUSEPORT:每个实例监听同一端口,内核按连接四元组哈希分发,因此不需要网关就能做到单端口多副本负载均衡。要求 bun >= 1.4.0 或 node >= 24.0.0。
应用侧监听时必须打开 reusePort:
js
const PORT = Number(process.env.BM2_APP_PORT);
// Bun
Bun.serve({ port: PORT, reusePort: true, fetch: () => new Response("ok") });
// Node.js
const http = require("node:http");
http.createServer((req, res) => res.end("ok")).listen({ port: PORT, reusePort: true });开启 reusePort 是应用的责任,因为只有它知道自己的监听方式。bm2 在启动后实测这一点:如果没开,整个项目会被停止,所有实例进入 errored,原因记为 reuseport_missing。修正应用后重新 bm2 serve 即可,注册不会丢。
单个实例崩溃后自动重启并重新加入端口组,其余实例不受影响。BM2_APP_INSTANCE === "0" 的主实例判断在 cluster 模式下同样可用。
fork 模式
toml
exec_mode = "fork"
instances = 3
port = 3000端口从 port 起连续分配:3000、3001、3002。分发交给网关。
实例增减之后要同步更新 upstream 列表并 reload 网关——这是 fork 模式要求你做的那部分工作。
Nginx 示例(假设 instances = 2、port = 3000):
nginx
upstream bm2_app {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://bm2_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Caddy 示例:
text
example.com {
reverse_proxy 127.0.0.1:3000 127.0.0.1:3001
}网关与 bm2 的分工
bm2 只做进程托管,反向代理与负载均衡交给网关。两者的分界很清楚:
- cluster 模式:bm2 自己就是负载均衡层,网关只需要一条
server 127.0.0.1:3000;。实例增减不需要动网关配置。 - fork 模式:bm2 提供连续端口,网关负责分发,实例增减要更新 upstream。
需要域名、TLS 或跨机分发时,两种模式都要配网关——那时网关解决的是 bm2 不打算解决的问题。