网上开服务器的人多,但真正把“开服”这件事理清楚的教程不多。大部分教程要么只讲点击几个按钮,要么上来就丢一堆代码让小白照抄,中间的原理和坑完全不提。我自己用腾讯云搭 Minecraft Forge 服务端时踩过不少雷,从镜像选择到 JVM 参数调优都折腾过一遍,这篇就把完整过程写出来,包括为什么这样做、命令是什么意思、报错怎么排查,照着走基本能一次跑通。
这篇内容面向想自己和朋友一起玩 Forge 模组服的玩家,也适合刚接触 Linux 运维、想拿 Minecraft 当练手项目的开发者。涉及的服务器环境是腾讯云 CVM(重装系统后的通用流程对轻量应用服务器同样适用),服务端框架是 Forge 47.x(对应 Minecraft 1.20.1,Java 17),这些都是目前兼容性最稳的组合。
1. 方案选型:为什么是腾讯云、Forge 和 Linux
1.1 云服务器和家用机到底差在哪
很多人第一反应是用自己电脑开服,省一笔服务器钱。短期玩三五个人确实没问题,但连续开机几天后,CPU 温度、内存占用、家庭宽带的动态 IP 都会成为问题,更不用说上传带宽通常只有几十 Mbps,外网朋友一多延迟立刻飙升。
用云服务器的核心优势是稳定和可控。腾讯云的 CVM 实例可以按需升级配置,数据盘独立于系统盘,重装系统不怕存档丢失,安全组规则可以从端口层面直接挡住扫描流量。而且云厂商的机房带宽质量比家庭宽带上行稳定得多,这对多人同时在线很关键。
至于为什么选腾讯云而不是其他平台,主要是个人习惯:CVM 控制台的防火墙和安全组策略比较直观,镜像市场里的纯净系统镜像多,轻量应用服务器价格也友好。示例中用到的核心配置如下表,仅作参考,实际按预算和人数调整。
| 项目 | 示例配置 | 说明 |
|---|---|---|
| 实例规格 | 4核 8G | 支持 8~12 人同时在线、约 80 个模组 |
| 系统盘 | 40G SSD | 系统 + Minecraft 本体足够 |
| 数据盘 | 50G SSD | 存放世界存档、备份、日志 |
| 带宽 | 5Mbps 按流量 | 轻量应用服务器选“流量包”更省心 |
| 镜像 | Ubuntu 22.04 LTS | 干净、兼容性好、资料多 |
1.2 Forge 比 Fabric 更省心的原因
模组加载框架现在主流就是 Forge 和 Fabric 两套。Fabric 更轻量、更新快,很多新版本模组优先适配它;但如果你是奔着“经典整合包”去的,比如科技、魔法、冒险类的大型模组包,Forge 的生态明显更成熟,兼容性也更好。
Forge 的安装器本身就是个自解压程序,一条命令就能生成服务端目录、启动脚本和依赖库,不需要手动配置 classpath。这个设计对第一次开服的人很友好,不容易把启动参数写错。它的 mods 目录也符合 Java 开发的直觉:丢进去就加载,删掉就卸载,没有额外的初始化步骤。
从长期维护角度看,Forge 服务端的崩溃日志里会直接标注是哪个模组的哪个类报错,定位问题比 Fabric 方便一些。社区里“某某整合包用的什么版本 Forge”这类问题,答案基本都默认为 Forge,资源密度决定了你遇到问题时更容易搜到解决方案。
1.3 实例规格和带宽的具体选择思路
选配置的核心指标是同时在线人数和模组数量。模组数量影响的是内存,在线人数影响的是 CPU 和内存的双重压力。
- 1~3 人,模组少于 30 个:2核 4G 够用,但我会建议把
-Xmx设为 3G,留 1G 给系统。 - 4~8 人,模组 30~60 个:4核 8G 是舒服线,
-Xmx设 5G~6G。 - 8~15 人,模组 80 个以上:4核 16G 更稳,或者直接上 8核16G。
带宽上,Minecraft 的协议并不算吃带宽,但区块加载、玩家移动、箱子物品列表同步都会产生流量。5Mbps 带宽能应付 10 人左右的中小型服务器,如果你打算开放公网给陌生玩家,流量包模式会比固定带宽更划算。
地域选择上,离你和你的朋友最近的城市节点最好。腾讯云国内地域之间的延迟差异不大,华南选广州、华北选北京,华东选上海,不用太纠结。
2. 购买与登录准备:从零开始拿到可操作的 Ubuntu 环境
2.1 系统镜像选择的细节
腾讯云购买实例时,系统镜像默认可能是 CentOS 或者 Windows Server。我的建议是如果你不熟悉 Windows 服务器运维,就选 Ubuntu 22.04 LTS。原因有几个:Java 相关的依赖 apt 直接装最省事;Forge 服务端开箱即用的run.sh在 Ubuntu 上没有任何路径问题;社区里搜 “Ubuntu minecraft server” 资料也最多。
如果你有 Windows 服务器运维基础,用 Windows Server 也能跑,但要注意一点:不要在服务器上装完整版 Java for Windows 时勾选捆绑的“Ask Toolbar”之类的插件,环境变量JAVA_HOME也必须手动配好,这比 Linux 上多一步。
确定 Ubuntu 22.04 LTS 后,登录方式建议用密钥而不是密码。密钥登录比密码安全得多,也能避免因为弱密码被爆破。腾讯云控制台在创建实例时可以直接生成密钥对,下载的私钥文件要保存好,丢了就只能重置密码。
2.2 远程登录和文件上传:CRT、WinSCP、scp 三件套
我在实际操作中最顺手的方式是配一个 SecureCRT 会话,用 SSH 私钥登录。配置过程比较复杂,一把梭有问题的话,推荐先在腾讯云控制台使用“OrcaTerm”网页终端确认系统状态,再回到本地配置客户端。
SecureCRT 配置密钥登录的关键步骤,记住一个原则:私钥格式要明确。
- 腾讯云生成的私钥是
.pem格式,SecureCRT 需要把它转换成 OpenSSH 格式或者直接用 PuTTY 转换器转成.ppk。 - 在会话的 Properties -> Connection -> SSH2 -> Authentication 里选择 PublicKey,并导入你的私钥文件。
- 用户名是
ubuntu(腾讯云 Ubuntu 镜像的默认用户,不是 root)。
如果你不喜欢 CRT,用系统自带的 OpenSSH 客户端在终端里直接执行也可以:
chmod 400 my-key.pem ssh -i my-key.pem ubuntu@你的公网IP文件上传是开服过程中几乎每天都在用的事。上传 mod、替换配置、下载存档备份,我用 WinSCP 或scp命令的方式比较多。
scp -i my-key.pem -r ./mods ubuntu@你的公网IP:/home/ubuntu/minecraft/mods这条命令把本地的整个mods目录递归上传到服务器指定路径。-r参数不能少,不用-r就只能传单个文件。
2.3 安全组与防火墙端口规划
Minecraft Java 版默认端口是25565/TCP,局域网联机时一般是25565,Forge 服务端默认也是这个。如果开了 Query 端口则额外需要25565/UDP,但大多数场景只需要 TCP 就够了。
腾讯云 CVM 的安全组规则要放行TCP:25565。轻量应用服务器则是在“防火墙”页面添加一条“端口 25565,协议 TCP”的规则。两个平台的操作入口不一样,但目标一致:让外网能够访问到 Minecraft 的监听端口。
除了 25565,我强烈建议把 SSH 端口(默认 22)的访问来源限制到你自己的 IP 网段。安全组允许“来源 IP”配置,填你的公网IP/32作为来源,别人就扫不到你的 SSH 端口了。
到了 Ubuntu 内部,如果启用了 ufw 防火墙,还要额外放行:
sudo ufw allow 25565/tcp sudo ufw allow 22/tcp sudo ufw enableufw enable前务必确认 22 端口已放行,不然你会把自己锁在外面。轻量应用服务器如果已经在控制台开放了端口,且系统镜像默认没启用 ufw,可以跳过这一步。
3. 安装 Java 与 Forge:多数人在这里翻车
3.1 JDK 版本别装错:Java 17 还是 21?
Minecraft 1.20.1 对应的 Forge 47.x 官方要求 Java 17,这是硬性版本要求。高版本的 Java 21 不是不能用,部分模组会因为使用了旧字节码而报UnsupportedClassVersionError,我建议直接安装 OpenJDK 17,别折腾。
sudo apt update sudo apt install openjdk-17-jdk-headless -y java -version最后一条命令必须看到类似openjdk version "17.0.x"的输出。如果系统里之前装过别的 Java 版本,可以用update-alternatives --config java切换默认版本。
我再补充一个小经验:如果你打算以后玩 1.21 之类的更新版本,服务器的 JDK 版本可能要升到 21,但同一个系统里可以共存多个 JDK。开服脚本里写清楚用哪个java二进制就行,不用卸载旧的。
3.2 Forge 安装器的运行原理和安装命令
从 Forge 官网下载对应版本的 installer,文件名大概是forge-1.20.1-47.3.0-installer.jar。很多人以为要双击运行,其实在服务器上把它当成普通的 Java 程序执行即可。
# 先建一个干净目录,不然后面目录结构会很乱 mkdir -p ~/minecraft cd ~/minecraft # 上传 installer 后,执行服务端安装 java -jar forge-1.20.1-47.3.0-installer.jar --installServer命令中的--installServer是关键参数。它告诉安装器:只为服务端生成文件,不弹出图形界面。执行完成后,目录里会多出:
libraries:Forge 依赖的所有第三方库mods:空的模组目录run.sh:Linux 启动脚本run.bat:Windows 启动脚本user_jvm_args.txt:JVM 参数文件server.properties:服务端配置文件
安装器全程没有输出一大堆日志是正常的,只要命令退出没有ERROR就算成功。如果下载依赖库时网络波动导致下载失败,重跑一次--installServer即可,它会跳过已完成的文件。
3.3 首次启动、EULA 同意与目录文件说明
第一次运行run.sh前要改一个文件,这也是新手最常见的报错来源:
You need to agree to the EULA before running the server.Minecraft 服务端默认在eula.txt里写着eula=false,不改成true就会启动失败。改法:
cd ~/minecraft # 首次启动先运行一次,让服务端生成 eula.txt 等文件 ./run.sh # 看到 EULA 报错后,修改文件 sed -i 's/eula=false/eula=true/' eula.txt然后再次./run.sh。首次启动要生成世界地图、加载 Forge 模组注册表,通常需要几十秒到几分钟,看到Done (X.XXXs)! For help, type "help"就代表服务端已经正常启动。
第一次启动后最好在控制台输个stop正常关服。这样世界数据能安全落盘。直接kill进程虽然也能关,但可能导致存档写入不完整。
stop这个过程会生成world目录、logs目录、level.dat等文件。之后每次开服,world目录就是你要备份的核心。
4. 服务端配置与模组管理:上线前的必要调整
4.1 server.properties 的关键参数
Minecraft 服务端几乎所有行为都集中在server.properties里。我用下来最需要改的就是下面几个,不是所有参数都要动,但改错一个就可能导致连接失败或体验极差。
| 参数 | 推荐值 | 说明 |
|---|---|---|
server-port | 25565 | 默认不用动,除非你想跑多个实例 |
motd | 自定义一句话 | “欢迎来到 xxx 服务器”这类 |
online-mode | true | 正版服必须 true;离线服设 false 但风险自负 |
max-players | 10 | 根据实例规格调整,别大于实际承受能力 |
view-distance | 8~10 | 越大越吃 CPU,8 是平衡点 |
difficulty | normal | 当然也可以 hard,看你想怎么玩 |
white-list | true | 强烈建议开,防止陌生人进服破坏 |
spawn-protection | 0 | 否则出生点附近无法破坏方块,很烦 |
pvp | true | 按你的服务器规则来 |
level-seed | 留空 | 有想用种子地图再填 |
如果你之前玩过单机,对difficulty、pvp肯定不陌生。这里特别注意online-mode=true时,所有玩家账号必须是正版账号;如果开的是离线服(online-mode=false),建议配合白名单使用。
# 开启白名单 sed -i 's/white-list=false/white-list=true/' server.properties之后在游戏控制台输入whitelist add 玩家ID即可添加白名单。添加后立刻生效,玩家不用重启游戏,这里我实测过很多次,确认是即时生效的。
4.2 上传和安装模组
Forge 模组上传到服务器的mods目录,启动时就会加载。但这里有一个最容易忽略的原则:客户端和服务端的 mod 必须一致,服务端还要额外兼容服务端专用 mod(如性能优化类)。如果只往服务器丢 mod,玩家端没装,进服时会被提示缺少某些物品或方块。
模组版本冲突是另一个问题。服务端日志里常见的DuplicateModsFoundException就是模组重复或版本不一致导致的。我的排查习惯是:
# 查看启动日志末尾是否有异常 tail -n 50 logs/latest.log日志里会明确列出哪些模组版本冲突。
上传方式我是这样做的:先把整合包在本地单人模式跑一遍,确认不崩溃,再把mods目录用前面提到的scp或者 WinSCP 整体传到服务器覆盖。
4.3 开服后的首次联机测试
服务器启动且玩家准备就绪后,客户端多人游戏地址填你的服务器公网IP:25565,例如119.3.x.x:25565,端口不是默认时就要显式写。如果填了端口却连不上,大概率是安全组或防火墙没放行,而不是服务端配置问题。
这里有个小技巧:先在服务器本机用curl或nc测试端口监听状态。
ss -tlnp | grep 25565看到LISTEN状态,说明 Minecraft 进程已经绑定端口。如果没有任何输出,说明服务端可能还在加载或者启动失败,先去logs/latest.log看报错。
5. JVM 参数与内存优化:让服务器更流畅的关键
5.1 为什么默认参数不够用
Forge 的run.sh默认 JVM 参数比较保守,没有针对 Minecraft 的服务器模型优化。Minecraft 服务端有大量对象创建和持续 GC 压力,默认参数下经常出现周期性卡顿,表现就是玩家走到新区块时顿一下,或者多人同屏时 TPS 掉到十几。
TikTok 的 Aikar 团队曾经发布过一版针对 Minecraft 服务端的 JVM Flags,社区简称 Aikar's Flags。它调整了 G1GC 的新生代比例、GC 暂停时间目标、提前触发内存 Touch 等参数,实测能让区块加载和实体运算的卡顿明显减少。这个参数组合对 Forge 同样适用。
5.2 实操:修改 user_jvm_args.txt
Forge 推荐把 JVM 参数写在用户级user_jvm_args.txt里,run.sh会自动读取,不需要改启动脚本本身。文件里一行一个参数,举个例子(4核8G 实例,分配 5G 给 Minecraft):
-Xms5G -Xmx5G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:MaxTenuringThreshold=1 -XX:+PerfDisableSharedMem几个关键参数的解释:
-Xms和-Xmx必须一致,避免 JVM 动态伸缩堆大小带来的额外开销。建议设定为服务器可用内存的 60%~70%,比如 8G 机器给 5G。-XX:+AlwaysPreTouch会在启动时把内存全部映射到物理内存,启动变慢,但运行期更稳定,实测值得。-XX:MaxGCPauseMillis=200不能让 GC 一定低于 200ms,但为 G1 提供了明确的优化目标。-XX:+UnlockExperimentalVMOptions在 JDK 17 里某些 G1 参数仍标记为实验性,需要这个开关,否则直接退出启动也会报错。
改完参数建议重启一次服务端。观察项有两个:启动时内存是否平滑上升到设定值,玩家集中活动时 TPS 是否长期保持在 20(/tps命令可查)。如果 TPS 跌到 10 以下,说明配置确实不够或某个模组吃性能。
5.3 后台运行:screen、nohup 与 systemd
直接./run.sh运行的话,SSH 断开服务端就停了。最简单的办法是用screen让服务端在后台独立会话运行:
sudo apt install screen -y screen -S minecraft cd ~/minecraft ./run.sh # 退出当前 screen 会话,按 Ctrl+A 然后按 D之后想回到控制台,执行:
screen -r minecraft在 screen 会话里可以直接输入服务端命令,比如list查看在线玩家、save-all手动存档。
如果希望更工程化一点,用 systemd 服务托管的体验更好。写一个服务文件:
[Unit] Description=Minecraft Forge Server After=network.target [Service] User=ubuntu WorkingDirectory=/home/ubuntu/minecraft ExecStart=/home/ubuntu/minecraft/run.sh Restart=on-failure [Install] WantedBy=multi-user.target然后:
sudo systemctl daemon-reload sudo systemctl enable minecraft sudo systemctl start minecraft好处是开机自启、崩溃自动重启、日志统一走journalctl -u minecraft查看。缺点是想输入服务端命令时,系统 API 没有直接支持,需要辅助工具。对多数小服来说,screen 足够,不必上 systemd。
5.4 定时备份与存档管理
Minecraft 最怕的就是存档损坏。我吃过大亏:一次服务器断电,world目录里的区块数据写了一半,整个世界回滚到几小时前。从那以后我养成了一个习惯:每天凌晨自动打包备份。
sudo apt install cron -y crontab -e # 添加一行,每天凌晨 3 点执行备份 0 3 * * * tar -czf /home/ubuntu/backups/world-$(date +\%F-\%H\%M).tar.gz -C /home/ubuntu/minecraft world定期检查备份目录大小,及时清理旧备份:
find /home/ubuntu/backups -name "*.tar.gz" -mtime +7 -delete这条命令删除 7 天前的备份文件。如果空间不紧张,保留 14 天更稳妥。手动恢复时,把压缩包解压回world目录前一定要先停服,否则文件写冲突容易造成二次损坏。
6. 常见问题排查:端口、内存、模组冲突记录
6.1 客户端连不上服务器
这是一个经典问题的排查顺序,我建议按下面表格逐项检查,别一上来就怀疑服务器配置错了。
| 现象 | 可能原因 | 排查命令/操作 |
|---|---|---|
| 连接超时 | 安全组未放行 25565 | 腾讯云控制台安全组入站规则检查 |
| 连接被拒绝 | 防火墙拦截 / 服务端未启动 | ss -tlnp | grep 25565 |
| 一直正在登录 | online-mode 不一致 | 确认客户端正版登录状态与服务端设置匹配 |
| 进入后立刻掉线 | 登录服务器超时(正版验证) | 正版用户在客户端检查账户状态 |
| 连接后提示版本不匹配 | 客户端 Forge 版本和服务器不一致 | 客户端和服务端使用相同 Forge 版本 |
本机telnet 你的公网IP 25565是最直接的测试方式,但很多系统默认没装 telnet,用nc -zv 你的公网IP 25565也行。能通,就说明网络链路是通的,问题在应用层。
6.2 内存使用率持续攀升怎么办
Forge 服务器加载大量模组后,内存占用本身就会比原版高。如果发现内存稳定上涨最后 OOM 被系统杀掉(日志里出现Killed字样),最直接的原因要么是-Xmx给得太低,要么是某个模组存在内存泄漏。
先用 Spark 或观察 GC 日志定位,我常用spark这个性能分析模组:
/spark profiler --timeout 30 /spark heap dumpspark heap dump会生成一个 hprof 文件,用 VisualVM 打开可以看到对象占用。这个操作对很多人可能有点重,更快的办法是逐个排除:mods 目录里一半一半地移动模组,重启看内存,二分法能很快定位到罪魁祸首。
不过大部分情况下,单纯是-Xmx设置得太贪心。比如 4G 内存的机器设了-Xmx3.5G,系统本身还要吃掉 1G 左右,跑去 Swap 之后整个服务器就得卡成幻灯片。给系统至少留 20% 内存是我个人的硬性要求。
6.3 服务端启动失败,日志看不懂怎么办
常见启动失败分为三类:
- JDK 版本错误:日志提示
UnsupportedClassVersionError,确认java -version是 17。 - 模组冲突:日志直接列出
Modxxxhas been detected as duplicate或Missing dependencies。按提示找到对应模组调整版本即可。 - 端口被占用:日志提示
BindException: Address already in use。检查有没有重复实例在跑,ps aux | grep java把旧的 kill 掉再启动。
日志文件路径是logs/latest.log,每次启动会覆盖。logs/下还有带时间的旧日志,排查历史问题用它们。
6.4 TPS 低和区块卡顿的排查思路
TPS(Ticks Per Second)满值是 20。如果长时间低于 15,玩家会有明显卡顿感。排查优先级:
- 看
spark profiler结果,哪个线程占用 CPU 高。 - 把
view-distance降低 2~3 档,CPU 负载会立刻下降。 - 检查是否有大型红石机器、大量掉落物实体、村民聚集点在持续计算。
- 考虑安装性能优化模组,如
FerriteCore、MemoryLeakFix、Canary(需确认与你的 Forge 版本兼容)。
FerriteCore 对内存占用优化明显,实测在高模组数量下能减少几百 MB 内存;Canary 在 Forge 端的替代方案要看版本支持情况。注意这些本身就是模组,要服务端和客户端同时装才能完全生效,部分服务端专用的话玩家端可以不用装。
一些我最后想说的话
从“买服务器”到“朋友能进来玩”,整个过程里最让我印象深刻的不是哪条命令多高明,而是日志文件里那些明明写了答案、却因为没人解释而卡半天的细节。比如eula.txt那个坑,再比如用户ubuntu用 sudo 时需要输入密码却在脚本里被忽略。这些都属于知道一遍就再也不会犯、不知道就相当折磨的小问题。这篇文章把我踩过的这些坑和验证过的解法都摆出来了,你照着走一遍,应该能比当年的我省下至少一个晚上的折腾。
更进一步的话,你还可以在备份策略基础上接入对象存储 COS,把本地备份自动同步上云,防止服务器磁盘故障导致存档全没;也可以做一主一备的定时重建方案,把world目录定期复制到另一台机器。这些后续扩展都不难,但前提是先有一个跑得稳的 Forge 服。
如果你按这套流程把服务器跑起来了,中途有哪个环节和文章写的不一样,多半是系统版本或 Forge 版本差异导致的细节变化,优先看日志,它永远会告诉你真相。