饥荒联机版独立服务器分布式部署指南

0 背景介绍

通常情况下,饥荒联机版独立服务(后称“饥荒服务”)都是部署到同一台云服务器上,一般是森林+洞穴共两个世界,2核4G5M的云服务器配置就够用了。
但如果你的服务器比较多,可以尝试分布式部署。

比如说森林世界放到A服务器上,洞穴世界放到B服务器上(甚至还可以有森林世界2、森林世界3、洞穴世界2…等等),
这样理论上可以减轻单个服务器的压力,从而提升饥荒服务的性能。

但是经过我的测试,使用两台2核2G3M的服务器分别部署森林和洞穴,游戏体验还不如使用一台2核4G6M的服务器单机部署。至于原因你可以在阅读完本文后自行思考。

因此,本文实际用处并不大,仅供娱乐。

另外,本文默认你已经看过我写的另外一篇《饥荒独立服务器搭建》
文章,并且你已经有过成功搭建的经验了。

接下来介绍如何在两台云服务器上分别部署森林和洞穴,两台服务器的配置相同:

  • CPU:2核64位
  • 内存:2GB
  • 公网带宽:3Mbps
  • 操作系统:Debian12

假设服务器A用来部署森林、服务器B用来部署洞穴。

1 准备存档

我这里使用一个标准的“森林+洞穴”的存档测试,存档名称为Cluster_1,结构大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Cluster_1
├── Caves
│ ├── leveldataoverride.lua
│ ├── modoverrides.lua
│ ├── save
│ └── server.ini
├── Master
│ ├── leveldataoverride.lua
│ ├── modoverrides.lua
│ ├── save
│ └── server.ini
├── adminlist.txt
├── cluster.ini
└── cluster_token.txt

首先把这份存档分别放到两台云服务器上, 由于服务器A只运行森林世界、服务器B只运行洞穴世界, 因此可把服务器A中的Caves
文件夹删除、服务器B中的Master文件夹删除。

如果你的存档中没有adminlist.txtcluster_token.txt,或者想回顾下这两个文件的用途,
请回看我写的《饥荒独立服务器搭建》
文章。

2 修改存档配置文件

这部分我只列出关键参数,其余参数保持原样即可。

注意是“保持原样”,而不是“可有可无”!

2.1 森林世界(服务器A)中的cluster.ini文件

1
2
3
4
5
6
7
8
9
[SHARD]
# 设置为true
shard_enabled = true
# 设置为0.0.0.0
bind_ip = 0.0.0.0
# 这个参数可设可不设 如果设置了 请与洞穴世界中的该参数保持一致 若不设置 请直接删除该参数
master_port = 10888
# 必须设置 具体值随意 但要与洞穴世界中的该参数保持一致
cluster_key = MyPassword

2.2 森林世界(服务器A)中的Master/server.ini文件

1
2
3
[SHARD]
# 设置为true
is_master = true

2.3 洞穴世界(服务器B)中的cluster.ini文件

注意,洞穴世界中的该配置文件中的参数有一部分不会生效,因为这个文件和森林世界中的是一模一样的,
且森林世界的配置优先级更高,所以有些参数即使没配置或者配置的和森林世界不一样,最终也会以森林中的为准。

这部分参数我会在下面用“不生效”表示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[GAMEPLAY]
# 不生效
max_players = 4

[NETWORK]
# 不生效
lan_only_cluster = false
# 不生效
cluster_password =
# 不生效
cluster_description = 这是一条神奇的描述...
# 不生效
cluster_name = GZOnline

[SHARD]
# 设置为true
shard_enabled = true
# 设置成森林世界所在服务器的公网IP
master_ip = 12.34.56.78
# 这个参数可设可不设 如果设置了 请与森林世界中的该参数保持一致 若不设置 请直接删除该参数
master_port = 10888
# 必须设置 具体值随意 但要与洞穴世界中的该参数保持一致
cluster_key = MyPassword

2.4 洞穴世界(服务器B)中的Master/server.ini文件

1
2
3
[SHARD]
# 设置为false
is_master = false

3 修改启动脚本

这部分我只列出要修改的代码行,其余部分保持不变即可。

3.1 森林世界(服务器A)中的启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash

# 省略若干行
...

check_for_file "steamcmd.sh"
check_for_file "$dontstarve_dir/$cluster_name/cluster.ini"
check_for_file "$dontstarve_dir/$cluster_name/cluster_token.txt"
check_for_file "$dontstarve_dir/$cluster_name/Master/server.ini"
# 注释或删除下面这行
# check_for_file "$dontstarve_dir/$cluster_name/Caves/server.ini"

# 省略若干行
...

# 注释或删除下面这行
# "${run_shared[@]}" -shard Caves | sed 's/^/Caves: /' &
"${run_shared[@]}" -shard Master | sed 's/^/Master: /'

3.2 洞穴世界(服务器B)中的启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

# 省略若干行
...

check_for_file "steamcmd.sh"
check_for_file "$dontstarve_dir/$cluster_name/cluster.ini"
check_for_file "$dontstarve_dir/$cluster_name/cluster_token.txt"
# 注释或删除下面这行
# check_for_file "$dontstarve_dir/$cluster_name/Master/server.ini"
check_for_file "$dontstarve_dir/$cluster_name/Caves/server.ini"

# 省略若干行
...

# 删除最后的&符号
"${run_shared[@]}" -shard Caves | sed 's/^/Caves: /'
# 注释或删除下面这行
# "${run_shared[@]}" -shard Master | sed 's/^/Master: /'

修改脚本后,两台服务器分别启动饥荒服务,正常情况下,两台服务器的启动日志最终应大致如下:

  • 森林世界(Master)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Master: [00:00:37]: [Shard] Starting master server
Master: [00:00:37]: [Shard] Shard server started on port: 10888
Master: [00:00:37]: Telling Client our new session identifier: xxxxxxxxxx
Master: [00:00:37]: Check for write access: TRUE
Master: [00:00:37]: Check for read access: TRUE
Master: [00:00:37]: Available disk space for save files: 28301 MB
Master: [00:00:37]: ModIndex: Load sequence finished successfully.
Master: [00:00:37]: Reset() returning
Master: [00:00:39]: Validating portal[1] <-> 2[1] (inactive)
Master: [00:00:39]: Validating portal[10] <-> 2[10] (inactive)
Master: [00:00:39]: Validating portal[9] <-> 2[9] (inactive)
Master: [00:00:39]: Validating portal[8] <-> 2[8] (inactive)
Master: [00:00:39]: Validating portal[4] <-> 2[4] (inactive)
Master: [00:00:39]: Validating portal[5] <-> 2[5] (inactive)
Master: [00:00:39]: Validating portal[11] <-> 3[11] (inactive)
Master: [00:00:39]: Validating portal[7] <-> 2[7] (inactive)
Master: [00:00:39]: Validating portal[6] <-> 2[6] (inactive)
Master: [00:00:39]: Validating portal[3] <-> 2[3] (inactive)
Master: [00:00:39]: Validating portal[2] <-> 2[2] (inactive)
Master: [00:00:39]: Sim paused
Master: [00:00:40]: Server registered via geo DNS in ap-southeast-1
Master: [00:00:45]: [Shard] Secondary shard GZOnlineCaves(2) connected: xxx.xxx.xxx.xxx
Master: [00:00:46]: [Shard] Secondary GZOnlineCaves(2) ready!
Master: [00:00:46]: World 2(GZOnlineCaves) is now connected
Master: [00:00:46]: [SyncWorldSettings] Sending master world option ghostsanitydrain = none to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option darkness = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option resettime = none to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option hunger = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option healthpenalty = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option temperaturedamage = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option spawnmode = fixed to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option shadowcreatures = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option ghostenabled = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option brightmarecreatures = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option lessdamagetaken = none to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option portalresurection = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option basicresource_regrowth = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option krampus = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Sending master world option dropeverythingondespawn = default to secondary shards.
Master: [00:00:46]: Validating portal[1] <-> 2[1] (active)
Master: [00:00:46]: Validating portal[10] <-> 2[10] (active)
Master: [00:00:46]: Validating portal[9] <-> 2[9] (active)
Master: [00:00:46]: Validating portal[8] <-> 2[8] (active)
Master: [00:00:46]: Validating portal[4] <-> 2[4] (active)
Master: [00:00:46]: Validating portal[5] <-> 2[5] (active)
Master: [00:00:46]: Validating portal[7] <-> 2[7] (active)
Master: [00:00:46]: Validating portal[6] <-> 2[6] (active)
Master: [00:00:46]: Validating portal[3] <-> 2[3] (active)
Master: [00:00:46]: Validating portal[2] <-> 2[2] (active)
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option ghostsanitydrain = none to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option darkness = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option resettime = none to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option hunger = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option healthpenalty = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option temperaturedamage = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option spawnmode = fixed to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option shadowcreatures = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option ghostenabled = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option brightmarecreatures = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option lessdamagetaken = none to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option portalresurection = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option basicresource_regrowth = always to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option krampus = default to secondary shards.
Master: [00:00:46]: [SyncWorldSettings] Resyncing master world option dropeverythingondespawn = default to secondary shards.
  • 洞穴世界(Caves)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Caves:  [00:01:23]: [Shard] Connecting to master...
Caves: [00:01:23]: [Shard] Sending secondary shard information to master...
Caves: [00:01:23]: Received MasterInfoPacket row xxxxxxx region ap-southeast-1
Caves: [00:01:23]: Obtaining secondary shard IP from ap-southeast-1 lobby
Caves: [00:01:24]: [Shard] secondary shard is now ready!
Caves: [00:01:24]: World 1(Master) is now connected
Caves: [00:01:24]: Validating portal[9] <-> 1[9] (active)
Caves: [00:01:24]: Validating portal[1] <-> 1[1] (active)
Caves: [00:01:24]: Validating portal[2] <-> 1[2] (active)
Caves: [00:01:24]: Validating portal[3] <-> 1[3] (active)
Caves: [00:01:24]: Validating portal[8] <-> 1[8] (active)
Caves: [00:01:24]: Validating portal[10] <-> 1[10] (active)
Caves: [00:01:24]: Validating portal[7] <-> 1[7] (active)
Caves: [00:01:24]: Validating portal[6] <-> 1[6] (active)
Caves: [00:01:24]: Validating portal[4] <-> 1[4] (active)
Caves: [00:01:24]: Validating portal[5] <-> 1[5] (active)
Caves: [00:01:24]: [SyncWorldSettings] recieved world settings from master shard. true
Caves: [00:01:24]: [SyncWorldSettings] applying temperaturedamage = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying spawnmode = fixed from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying lessdamagetaken = none from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying ghostenabled = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying shadowcreatures = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying resettime = none from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying krampus = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying ghostsanitydrain = none from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying healthpenalty = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying dropeverythingondespawn = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying darkness = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying portalresurection = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying brightmarecreatures = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying hunger = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying basicresource_regrowth = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] recieved world settings from master shard. true
Caves: [00:01:24]: [SyncWorldSettings] applying temperaturedamage = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying spawnmode = fixed from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying lessdamagetaken = none from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying ghostenabled = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying shadowcreatures = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying resettime = none from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying krampus = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying ghostsanitydrain = none from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying healthpenalty = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying dropeverythingondespawn = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying darkness = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying portalresurection = always from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying brightmarecreatures = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying hunger = default from master shard.
Caves: [00:01:24]: [SyncWorldSettings] applying basicresource_regrowth = always from master shard.
Caves: [00:01:25]: Available disk space for save files: 30687 MB
Caves: [00:01:25]: Serializing world: session/308C4C95C17669ED/0000001637
Caves: [00:01:25]: [Shard] secondary shard LUA is now ready!
Caves: [00:01:25]: Sim paused

4 配置云服务器防火墙

再次回看上述的配置文件中如下参数所配置的值并记录:

  • 森林世界(服务器A)cluster.ini文件中的master_port。若未配置,则记作10888;
  • 森林世界(服务器A)Master/server.ini文件中的server_port。若未配置,则记作10999;
  • 森林世界(服务器A)Master/server.ini文件中的authentication_port。若未配置,则记作8766;
  • 森林世界(服务器A)Master/server.ini文件中的master_server_port。若未配置,则记作27016;
  • 洞穴世界(服务器B)Caves/server.ini文件中的server_port。若未配置,则记作10999;
  • 洞穴世界(服务器B)Caves/server.ini文件中的authentication_port。若未配置,则记作8766;
  • 洞穴世界(服务器B)Caves/server.ini文件中的master_server_port。若未配置,则记作27016;

在云服务器平台的防火墙配置中将上述各自设置的端口号放行,协议为UDP。

5 性能优化

如果服务器内存不够用可通过执行如下命令给云服务器分配虚拟内存:

1
2
3
4
5
6
7
# 其中2G表示分配2GB的虚拟内存
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效 否则服务器重启后虚拟存储会失效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab