强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

12 - 多服务器架构

12 - 多服务器架构

12.1 为什么需要多服务器

12.1.1 单服的局限性

问题说明
CPU 单线程瓶颈Minecraft 主循环是单线程的
内存上限JVM 堆不建议超过 24GB
玩家上限单服通常 100-200 人为上限
游戏模式隔离不同玩法互相影响
更新需要停服维护时所有玩家无法游戏

12.1.2 多服务器架构

                    ┌─────────────┐
  玩家 ──────────►  │   代理      │
  (端口 25577)      │  Velocity   │
                    └──────┬──────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
        ┌──────────┐ ┌──────────┐ ┌──────────┐
        │ 生存服   │ │ 创造服   │ │ 小游戏服 │
        │ :25565   │ │ :25566   │ │ :25567   │
        └──────────┘ └──────────┘ └──────────┘

12.2 代理服务器对比

12.2.1 代理类型

代理维护者性能特点推荐
BungeeCordSpigotMC⭐⭐⭐原始代理,功能基础旧项目
WaterfallPaperMC⭐⭐⭐⭐BungeeCord 优化版已停更
VelocityPaperMC⭐⭐⭐⭐⭐全新设计,推荐使用⭐ 强烈推荐

12.2.2 Velocity 优势

特性BungeeCordVelocity
性能中等高(Netty 优化)
内存占用较高
Forge/Fabric 支持有限完整
Modern Forwarding
配置格式YAMLTOML
插件生态丰富增长中
安全性中等

结论:新项目请选择 Velocity。BungeeCord/Waterfall 仅在已有项目迁移时考虑。


12.3 Velocity 部署

12.3.1 下载与安装

# 创建 Velocity 目录
mkdir -p /opt/minecraft/velocity
cd /opt/minecraft/velocity

# 下载最新 Velocity
wget -O velocity.jar https://api.papermc.io/v2/projects/velocity/versions/3.3.0-SNAPSHOT/builds/395/downloads/velocity-3.3.0-SNAPSHOT-395.jar

# 首次启动生成配置文件
java -jar velocity.jar --version

# 同意 EULA
echo "eula=true" > eula.txt

12.3.2 Velocity 核心配置

# velocity.toml

# 代理监听端口
bind = "0.0.0.0:25577"

# 服务器显示名称
motd = "§6§l我的服务器群组 §7- §eVelocity 代理"

# 显示服务器列表中的玩家数量
show-max-players = 500

# 是否限制最大玩家数
player-info-forwarding = "modern"

# 正版验证
online-mode = true

# 后端服务器列表
[servers]
survival = "127.0.0.1:25565"
creative = "127.0.0.1:25566"
lobby = "127.0.0.1:25567"

# 尝试顺序(玩家默认进入的服务器)
try = [
    "lobby",
    "survival"
]

# 强制默认服务器(玩家加入时的默认服务器)
forced-hosts = {}

# 超时设置(毫秒)
[connection-timeout]
connect = 5000
read = 30000

# 玩家信息转发模式
[player-info-forwarding]
mode = "modern"
# modern 模式需要子服禁用 online-mode
# 并在 Paper 的 paper-global.yml 中启用 velocity forwarding

# 高级设置
[advanced]
# 压缩阈值
compression-threshold = 256
# 压缩级别
compression-level = -1
# 登录速率限制
login-ratelimit = 3000
# 连接速率限制
connection-throttle = 4000
# 自动发送客户端列表
announce-forge = false
# ping 防洪
ping-passthrough = "DISABLED"
# 现代密钥交换
modern-key-encryption = true
# 现代玩家信息转发
modern-player-info-forwarding = true
# BungeeCord 插件消息通道
bungee-plugin-message-channel = true
# 展示 ping 信息
show-ping-requests = false
# 转发源 IP
forwarding-secret-file = "forwarding.secret"

12.3.3 子服 Paper 配置

每个子服需要配合 Velocity 进行配置:

# 子服 server.properties
online-mode=false
# 关闭正版验证,由 Velocity 处理
# 子服 config/paper-global.yml
proxies:
  velocity:
    enabled: true
    online-mode: true
    # 此 secret 必须与 velocity.toml 中的 forwarding.secret 一致
    secret: "your_forwarding_secret_here"
# 复制 forwarding.secret 到所有子服
cp /opt/minecraft/velocity/forwarding.secret /opt/minecraft/survival/
cp /opt/minecraft/velocity/forwarding.secret /opt/minecraft/creative/
cp /opt/minecraft/velocity/forwarding.secret /opt/minecraft/lobby/

12.4 BungeeCord 部署(备选)

12.4.1 BungeeCord 配置

# config.yml

ip_forward: true        # 必须为 true,转发玩家真实 IP
online_mode: true       # 正版验证
player_limit: 100
log_commands: false
log_pings: true
connection_throttle: 4000
prevent_proxy_connections: false
server_connect_timeout: 5000
remote_ping_timeout: 5000
remote_ping_cache: -1
forge_support: true
reject_transfers: false
timeout: 30000

servers:
  survival:
    motd: '&6生存服'
    address: 127.0.0.1:25565
    restricted: false
  creative:
    motd: '&a创造服'
    address: 127.0.0.1:25566
    restricted: false
  lobby:
    motd: '&b大厅'
    address: 127.0.0.1:25567
    restricted: false

forced_hosts:
  survival.example.com: survival
  creative.example.com: creative

listeners:
  - host: 0.0.0.0:25577
    bind_local_host: true
    ping_passthrough: false
    query_enabled: false
    query_port: 25577
    proxy_protocol: false
    forced_hosts:
      survival.example.com: survival
      creative.example.com: creative
    tab_list: GLOBAL_PING
    tab_size: 60
    default_server: lobby
    fallback_server: lobby

ip_forward: true
network:
  compression_threshold: 256
  compression_level: -1
  bind_local_address: true
  host: 0.0.0.0
  max_players: 100
  tab_size: 60
  throttle: 4000
# 子服 spigot.yml
settings:
  bungeecord: true   # 必须设为 true

12.5 多服务器管理

12.5.1 服务器间传送

# Velocity/BungeeCord 命令
/server survival           # 传送到生存服
/server creative           # 传送到创造服

# 使用插件(如 BungeeSuite, RedisBungee)
# 可以实现更复杂的传送功能

12.5.2 共享数据方案

数据类型方案说明
权限LuckPerms + MySQL所有服共享同一数据库
经济CMI + MySQL跨服经济
聊天RedisBungee跨服聊天
传送BungeeSuite跨服传送
Tab 列表TAB + Redis跨服 Tab

12.5.3 LuckPerms 多服配置

# 所有子服的 LuckPerms 配置
storage-method: mysql
data:
  address: "mysql-host:3306"
  database: "luckperms"
  username: "minecraft"
  password: "password"

# Velocity 代理的 LuckPerms 配置
# 用于管理代理级别的权限
storage-method: mysql
data:
  address: "mysql-host:3306"
  database: "luckperms"
  username: "minecraft"
  password: "password"
  table-prefix: "luckperms_proxy_"

12.5.4 RedisBungee 跨服通信

# plugins/RedisBungee/config.yml
# 安装 RedisBungee 可实现跨服玩家数据共享

redis:
  host: "redis-host"
  port: 6379
  password: ""
  database: 0

# 支持的功能
# - 跨服玩家计数
# - 跨服消息
# - 跨服传送
# - 共享 Tab 列表

12.6 启动脚本

12.6.1 Velocity 启动脚本

#!/bin/bash
# start-velocity.sh

cd /opt/minecraft/velocity

java \
  -Xms512M \
  -Xmx1G \
  -XX:+UseG1GC \
  -XX:G1HeapRegionSize=4M \
  -XX:+UnlockExperimentalVMOptions \
  -XX:+ParallelRefProcEnabled \
  -XX:+AlwaysPreTouch \
  -XX:MaxTenuringThreshold=1 \
  -jar velocity.jar \
  --nogui

12.6.2 批量管理脚本

#!/bin/bash
# manage-all.sh - 多服务器管理脚本

ACTION="$1"
SCREEN_PREFIX="mc"

case "$ACTION" in
    start)
        echo "启动所有服务器..."
        screen -dmS ${SCREEN_PREFIX}-velocity /opt/minecraft/velocity/start.sh
        sleep 2
        screen -dmS ${SCREEN_PREFIX}-survival /opt/minecraft/survival/start.sh
        screen -dmS ${SCREEN_PREFIX}-creative /opt/minecraft/creative/start.sh
        echo "所有服务器已启动"
        ;;
    stop)
        echo "停止所有服务器..."
        screen -S ${SCREEN_PREFIX}-survival -p 0 -X eval 'stuff "stop\015"'
        screen -S ${SCREEN_PREFIX}-creative -p 0 -X eval 'stuff "stop\015"'
        sleep 10
        screen -S ${SCREEN_PREFIX}-velocity -p 0 -X eval 'stuff "shutdown\015"'
        echo "所有服务器已停止"
        ;;
    restart)
        $0 stop
        sleep 5
        $0 start
        ;;
    status)
        echo "=== 服务器状态 ==="
        for s in velocity survival creative; do
            if screen -list | grep -q "${SCREEN_PREFIX}-${s}"; then
                echo "✅ ${s}: 运行中"
            else
                echo "❌ ${s}: 已停止"
            fi
        done
        ;;
    *)
        echo "用法: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

12.7 Docker 多服务器架构

12.7.1 完整 Docker Compose

# docker-compose-multi.yml

services:
  velocity:
    image: itzg/minecraft-server
    container_name: mc-velocity
    ports:
      - "25577:25577"
    environment:
      TYPE: "VELOCITY"
      MEMORY: "1G"
      EULA: "TRUE"
    volumes:
      - velocity-data:/data
    restart: unless-stopped
    networks:
      - mc-net

  survival:
    image: itzg/minecraft-server
    container_name: mc-survival
    environment:
      TYPE: "PAPER"
      VERSION: "1.21.4"
      MEMORY: "4G"
      EULA: "TRUE"
      ONLINE_MODE: "FALSE"
    volumes:
      - survival-data:/data
    restart: unless-stopped
    networks:
      - mc-net

  creative:
    image: itzg/minecraft-server
    container_name: mc-creative
    environment:
      TYPE: "PAPER"
      VERSION: "1.21.4"
      MEMORY: "2G"
      EULA: "TRUE"
      ONLINE_MODE: "FALSE"
      MODE: "creative"
    volumes:
      - creative-data:/data
    restart: unless-stopped
    networks:
      - mc-net

  mysql:
    image: mysql:8.0
    container_name: mc-mysql
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: luckperms
      MYSQL_USER: minecraft
      MYSQL_PASSWORD: mcpassword
    volumes:
      - mysql-data:/var/lib/mysql
    restart: unless-stopped
    networks:
      - mc-net

  redis:
    image: redis:7-alpine
    container_name: mc-redis
    command: redis-server --requirepass redispassword
    volumes:
      - redis-data:/data
    restart: unless-stopped
    networks:
      - mc-net

volumes:
  velocity-data:
  survival-data:
  creative-data:
  mysql-data:
  redis-data:

networks:
  mc-net:
    driver: bridge

12.8 多服务器监控

12.8.1 mc-monitor

# 安装 mc-monitor
# 它是 itzg/mc-monitor 的独立工具

# 检查服务器状态
docker run --rm itzg/mc-monitor status \
  --host survival \
  --port 25565

12.8.2 自动健康检查脚本

#!/bin/bash
# health-check.sh - 检查所有子服健康状态

VELOCITY="localhost:25577"
SERVERS=("localhost:25565" "localhost:25566" "localhost:25567")
NAMES=("survival" "creative" "lobby")

check_server() {
    local host="$1"
    local port="$2"
    local name="$3"

    if timeout 5 bash -c "echo > /dev/tcp/$host/$port" 2>/dev/null; then
        echo "✅ ${name} (${host}:${port}): 正常"
    else
        echo "❌ ${name} (${host}:${port}): 无法连接"
        # 自动重启
        docker restart mc-${name}
    fi
}

echo "=== 服务器健康检查 ==="
echo "时间: $(date)"

check_server "localhost" "25577" "velocity"
for i in "${!SERVERS[@]}"; do
    IFS=':' read -r host port <<< "${SERVERS[$i]}"
    check_server "$host" "$port" "${NAMES[$i]}"
done

12.9 常见问题

Q1:玩家无法通过代理连接到子服?

# 1. 检查 Velocity 配置中的服务器地址和端口
# 2. 确认子服 server.properties 中 online-mode=false
# 3. 确认 forwarding.secret 一致
# 4. 检查防火墙规则
# 5. 检查日志
docker logs mc-velocity
docker logs mc-survival

Q2:Modern Forwarding 不工作?

# 确保:
# 1. velocity.toml 中 player-info-forwarding = "modern"
# 2. 子服 paper-global.yml 中 velocity.enabled = true
# 3. forwarding.secret 在所有服务器中一致
# 4. 子服 server.properties 中 online-mode=false

Q3:如何实现子服自动重启?

# Docker 中使用 restart: unless-stopped
# 或使用 systemd 管理
# 或使用守护进程脚本
while true; do
    java -jar paper.jar --nogui
    echo "服务器将在 5 秒后重启..."
    sleep 5
done

12.10 本章小结

要点说明
Velocity 是推荐代理性能和安全性均优于 BungeeCord
Modern Forwarding 转发玩家信息确保所有服务器的 secret 一致
子服 online-mode 必须为 false由代理处理正版验证
共享数据用 MySQL + Redis权限、经济、聊天跨服共享
Docker Compose 简化管理一键启动所有服务

扩展阅读