ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

末世塔防手游服务端手工搭建全流程:从环境部署到排错实战

末世塔防手游服务端手工搭建全流程:从环境部署到排错实战 我们先拿到游戏服务器配置文件后第一件事是认识清楚到底在搭什么。项目标题已经写得很明白了——末世塔防手游、服务端手工搭建、包含资源下载和部署过程。说白了就是把原本跑在官方机房的游戏服务端程序在我们自己控制的Linux服务器上完整跑起来同时让客户端能连上我们的服务器实现登录、创角、进副本、打僵尸这一整套闭环。这篇文章不是纸上谈兵。我会把整个手工搭建过程拆成六个阶段环境准备、依赖安装、资源上传、数据库初始化、服务端配置修改、启动验证与排错。整个过程中涉及的关键参数、配置文件位置、常见报错我都会按我实际踩过的坑来写。做这件事需要的基础是会看Linux命令行、知道MySQL的基本操作、理解IP端口这些网络概念。如果你纯小白建议先把Linux常用命令过一遍再来实操因为下面几乎每一步都绕不开命令行操作。1. 搭建前的整体思路与方案选型1.1 这套服务端到底由哪些部分组成先别急着动手装环境把服务端程序的构成搞清楚能省下一大半折腾时间。这类手游服务端虽然不同游戏之间有差异但主体结构基本是一致的我习惯把它分成四块来看。第一块是网关/登录服务。玩家打开客户端后第一个连上来的就是这个服务。它负责验证账号密码、分配游戏服务器列表、维持心跳连接。你可以把它理解成小区门口的门卫——所有玩家进出都得先经过它但它本身不负责太复杂的业务逻辑。第二块是游戏逻辑服务。这是整个服务端的核心大脑玩家进入游戏后的一切行为——移动、攻击、释放技能、拾取掉落、僵尸AI控制、掉落计算——全部由这里处理。它也是所有服务里最吃CPU和内存的进程部署时通常需要单独给它留足资源。第三块是数据库服务。游戏里所有持久化数据——账号信息、角色属性、背包物品、关卡进度——都存在这里。常见的是MySQL或MariaDB部分源码特别老的还会用MSSQL。我们的教程默认用MySQL 5.7这是这类手游服务端兼容性最好的版本之前试过8.0部分老程序会因为认证插件不兼容直接连不上库。第四块是世界/地图服务。负责场景同步、同屏玩家广播、NPC刷新管理。有些实现会把世界服务合并进逻辑服务里但独立出来性能更好调优。拿到一个未知的服务端压缩包时我的建议是先解压看目录结构。凡是带game、login、world、db这几个关键字的目录或可执行文件基本就是上面几块的对应程序。先画一张进程关系图再动手部署比盲目执行安装脚本要稳得多。1.2 服务器配置选型与操作系统选择服务端程序的资源消耗跟在线人数直接挂钩。对于学习搭建和少量朋友联机这种场景2核4G的云服务器或者虚拟机就够用了。但要注意如果解压出来的服务端里有个明显的“worldserver”或者“gameserver”进程而且还有一堆地图资源文件那建议至少上4核8G不然加载地图时内存直接爆掉。操作系统这块听我一句劝老老实实选CentOS 7.9或者Ubuntu 20.04 LTS。为什么不用更新的版本这套部署流程里依赖的MySQL 5.7、Nginx 1.18这些软件包在新系统上要么得换源要么得编译安装凭空多出不少坑。CentOS 7.9的生命周期虽然已结束但作为这类老旧游戏服务端的运行环境它反而是最省心的选择——包管理器里直接就有mysql57-community源不需要折腾编译安装。网络方面如果你的服务器有公网IP那直接绑定就行。如果只是内网测试那就用NAT模式把端口映射出来。服务端端口规划上我做了一个参考表供你对照服务模块默认端口用途说明配置位置登录网关8000客户端首次连接login目录下的config.ini或conf文件游戏逻辑8001游戏数据收发game目录下的world_config数据库3306数据读写my.cnf / my.ini资源下载/补丁80或8080客户端获取资源包nginx配置端口映射的原则是数据库端口不要暴露到公网仅本机回环地址访问就够了。客户端只跟登录网关和游戏逻辑端口通信其他端口一律不要对外放行。云服务器的话在安全组里只放行上述端口其他全部拒绝。1.3 部署方案一键脚本还是纯手工操作现在的服务端资源包基本分两类一类是冲好的“一键端”解压后执行start.sh就能启动另一类就是纯源码或纯程序集需要自己手动配置然后逐个启动进程。标题既然叫“手工搭建”我就重点讲手工流程但也会提一下怎么把手工步骤固化成一键脚本。我个人的经验是第一次搭建无论如何都要用手工方式走一遍全流程。一键端出问题时你根本不知道是哪个服务挂了、日志在哪、配置怎么改。手工搭过一遍之后你会对每个配置文件、每个启动依赖都心里有数下次再出错就能精准定位。而且手工搭建并不难无非就是“装依赖—传文件—改配置—导数据—启动”这五个大步骤每一步都有明确的操作对象和验证方法。2. 环境准备与核心依赖安装2.1 用到的软件栈与版本选择游戏服务端开发年代不同依赖的技术栈也不同。我遇到过的这套需要安装的软件包括JDK 1.8因为程序是Java写的、MySQL 5.7数据存储、Nginx资源文件分发。还有一类是用C写的服务端那种连JDK都不用装但需要额外装一些运行库。拿到服务端文件后先用file命令或者直接看启动脚本后缀来判断技术栈。如果你手上的服务端是.jar后缀的Java程序那核心依赖就是JDK。如果是可执行文件带.so动态库的那就是C程序需要确保glibc版本兼容——CentOS 7自带的glibc 2.17兼容性是最好的所以我才一直建议不要用太新的系统。以下是本教程使用的软件版本参考软件/组件推荐版本安装方式备注CentOS7.9系统安装最小化安装即可JDK1.8.0_202rpm包安装最后更新版1.8MySQL5.7.44yum源安装兼容老认证插件Nginx1.18yum源安装用于资源文件下载解压工具unzip、taryum安装必备小工具2.2 基础依赖安装的完整命令第一步先把系统基础工具装齐。# 更新系统并安装基础工具 yum install -y wget net-tools telnet lsof unzip tar vim # 如果是Ubuntu则用 apt-get update apt-get install -y net-tools unzip telnettelnet和lsof是我日常排查服务是否在监听、端口是否对外开放最常用的工具。lsof查看端口占用telnet测试远程端口通断这两个配合使用基本能解决八成的“连不上服务”问题。第二步安装JDKmkdir -p /data/tools cd /data/tools wget https://download.java.net/openjdk/jdk8u202/ri/openjdk-8u202-linux-x64.tar.gz tar -zxvf openjdk-8u202-linux-x64.tar.gz -C /usr/local/ # 配置环境变量 cat /etc/profile EOF export JAVA_HOME/usr/local/jdk8u202 export PATH$JAVA_HOME/bin:$PATH export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar EOF source /etc/profile # 验证版本 java -version第三步安装MySQL。这里要注意CentOS 7自带的yum源没有mysql57需要先安装官方的源rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm yum install -y mysql-community-server # 启动服务并设置开机自启 systemctl start mysqld systemctl enable mysqld # 获取初始化密码 grep temporary password /var/log/mysqld.log拿到临时密码后用mysql_secure_installation走一遍安全配置设置一个你记得住的root密码然后创建一个游戏专用的数据库账号。注意MySQL 5.7默认的密码策略比较严格初期测试可以把validate_password_policy先调低不然简单密码过不了。第四步安装Nginxyum install -y nginx systemctl start nginx systemctl enable nginxNginx在游戏服务端里的角色就是静态资源服务器。客户端启动时需要的更新包、补丁文件、配置文件以及服务端对外发布的公告图片都从Nginx这个端口上拉取。把整个资源包放到nginx的html目录之后客户端才能正常下载资源。2.3 数据库账号初始化和权限规划游戏服务端连接数据库一般不会用root账号。规范做法是创建一个最小权限的专用账号说白了就是让游戏程序只访问它需要的那个库这样即使后期程序出现安全问题攻击面也有限。-- 登录数据库后执行 CREATE DATABASE IF NOT EXISTS game_db DEFAULT CHARSET utf8mb4; -- 如果老服务端不支持utf8mb4就改用utf8 CREATE USER gamelocalhost IDENTIFIED BY Game2024!; GRANT ALL PRIVILEGES ON game_db.* TO gamelocalhost; FLUSH PRIVILEGES;这里刻意用localhost而不是%原因是游戏服务和数据库在同一台机器上没必要把数据库端口开放到外部。如果后续要拆库分离部署再把这个改成内网IP即可。我个人建议从一开始就养成“数据库不对外”的习惯安全风险能降一截。3. 游戏服务端资源的上传、校验与结构解读3.1 获取服务端资源并上传服务器游戏服务端资源包的获取途径通常是项目方提供的网盘链接或者交流群的共享文件。下载下来一般是压缩包格式zip最常见也有rar和7z。CentOS自带的unzip能解zip但rar和7z需要额外安装对应工具。拿到压缩包先不要急着解压到正式目录。先在本地或临时目录解压一遍确认里面文件的完整性——毕竟网盘下载中途断线的事情太常见了如果压缩包损坏后面的步骤全白做。正确做法是# 在本地校验压缩包是否完整以zip为例 unzip -t 游戏服务端源码.zip输出的最后一行会显示No errors detected in compressed data of 游戏服务端源码.zip看到这行才说明压缩包是好的可以上传。上传到服务器我推荐用scp命令scp /本地路径/游戏服务端源码.zip root服务器IP:/data/如果你用Windows本地上传文件可以用WinSCP这种图形化工具拖拽上传更直观。上传完毕后建议核对一下文件大小跟本地是否一致ls -l /data/游戏服务端源码.zip # 对比本地文件属性中的大小文件大小不一致就别接着往下做直接重新传。这是我踩过最冤枉的坑——花了两个小时配环境最后发现服务起不来是因为压缩包传了一半断掉服务端文件本身就是残缺的。3.2 解压并梳理服务端目录结构上传完成后在服务器上执行解压cd /data mkdir -p game-server unzip 游戏服务端源码.zip -d /data/game-server/ # 查看目录结构 ls -l /data/game-server/典型的游戏服务端目录大致长这样/data/game-server/ ├── login/ # 登录服务 │ ├── login.jar # 登录程序 │ ├── config.ini # 登录服务配置 │ └── start.sh # 启动脚本 ├── game/ # 游戏逻辑服务 │ ├── game.jar │ ├── config.ini │ └── start.sh ├── db/ # 数据库初始化脚本 │ └── init.sql # 建库建表及初始数据 └── res/ # 客户端资源文件 ├── patch/ # 补丁包 └── version.txt # 版本号文件拿到目录结构后花十分钟把所有start.sh打开看一眼把所有的config.ini、.xml、.yml配置文件梳理一遍搞清楚每个文件里有哪些参数需要改。这步做好后面的一切操作都是顺理成章的。重点要看的配置项包括数据库连接地址jdbc:mysql://...、端口号、心跳超时时间、日志输出级别。数据库连接地址是新手最容易漏改的——默认配置里写的是127.0.0.1:3306或者localhost如果你的数据库就在本机那倒不用改但你要是把服务端和数据库分开了这里不改的话就永远连不上库。3.3 资源文件的校验与补丁说明服务端资源目录里往往还有一个res或www目录里面放的是客户端需要的补丁资源。这个目录需要放到Nginx站点根目录下让客户端能通过HTTP拉取。# 把资源目录软链到nginx站点根目录也可以直接复制 ln -s /data/game-server/res /usr/share/nginx/html/game_res注意软链方式有个坑nginx进程默认以nginx用户运行如果你用了软链需要确保nginx用户对来源目录有读权限。实操中我遇到过权限不对导致客户端一直卡在资源加载界面的情况排查了半天发现是软链目录的父目录权限是700nginx用户根本没权限走进去。干脆改为直接复制省得权限问题cp -r /data/game-server/res /usr/share/nginx/html/game_res chmod -R 755 /usr/share/nginx/html/game_res4. 数据库初始化与配置修改实操4.1 导入数据库脚本并验证表结构服务端压缩包里一般会带数据库初始化脚本名字可能是init.sql、game.sql、db.sql之类的。先把脚本上传到服务器或直接在服务器里找到它的路径然后执行导入mysql -uroot -p -e source /data/game-server/db/init.sql导入过程中如果出现ERROR 1064之类的语法错误大概率是SQL脚本的MySQL版本兼容问题。老脚本里有时会用TYPEMyISAM这种老式写法在MySQL 5.7里已经被ENGINEMyISAM取代需要把脚本里的旧写法替换掉再导入。导入完成后检查核心表是否存在USE game_db; SHOW TABLES;正常情况至少能看到account账号表、player角色表、item物品表、server_list服务器列表这几类表。如果连表都没有说明脚本没执行成功别继续往下走先把导入问题解决再说。4.2 服务端配置文件逐项修改详解服务端配置修改是整个手工搭建的核心操作也是最容易出错的地方。我以最常见的Java服务端config.ini为例逐项拆解每个参数的含义和修改方式。# 登录服务配置示例 [server] id 1 name 僵尸末世-测试服 port 8000 max_user 1000 [database] host 127.0.0.1 port 3306 dbname game_db user game password Game2024!这里每一项都要跟你实际环境对应上server区id是服务器ID不能跟其他服冲突name会显示在客户端登录界面的服务器列表里port是监听端口防火墙和安全组要放行max_user是最大在线数测试环境开50-200就够开太大反而容易被僵尸号攻击后卡死。database区host如果数据库在本机就保持127.0.0.1不变如果数据库在其他机器要改成那台机器的内网IPdbname必须跟建库时的名字一致user和password是专门创建的数据库账号。游戏逻辑服务的配置也类似只是多了一些业务参数[game] clogin_port 8001 zone_id 1 init_gold 10000 init_diamond 500 drop_rate 1.0 exp_rate 1.0init_gold和init_diamond是新建角色送的初始资源drop_rate和exp_rate是掉落率和经验倍率。测试的时候可以把掉落率调高到2.0甚至5.0方便验证装备掉落功能是否正常。但注意这种倍率参数修改要谨慎等正式对外开服时如果忘了调回来经济系统就崩了。4.3 修改数据库里的服务器列表配置很多游戏架构里客户端登录后看到“服务器列表”是从数据库读取的而不是写在配置文件里的。这就需要在数据库里手动插入一条服务器信息USE game_db; INSERT INTO server_list (server_id, server_name, login_ip, login_port, game_ip, game_port, status) VALUES (1, 僵尸末世-测试服, 你的服务器公网IP或内网IP, 8000, 你的IP, 8001, 1);这里面的login_ip和game_ip要注意了如果客户端和内网玩就填服务器内网IP如果外网朋友要连就填公网IP。云服务器有时候有内网IP和公网IP之分这里填的是客户端访问时用的IP必须跟客户端网络可达。我见过很多新手卡在这一步服务端起来了、端口也监听了但客户端就是连不上原因就是数据库里填了内网IP而客户端在公网环境根本访问不到。4.4 服务端启动脚本的权限设置与启动方式配置文件改完后检查一下每个启动脚本是否有执行权限chmod x /data/game-server/*/start.sh有些启动脚本内部还会调用nohup把输出重定向到日志文件这很正常。但如果是手写启动Java程序建议先手动用前台模式启动一次确认没有报错后再改用后台脚本。手动前台启动异常时的错误信息最直观后台模式会把日志隐藏起来不利于第一次部署排查。# 进入登录服务目录前台启动一次看看 cd /data/game-server/login/ java -jar login.jar如果看到类似Server started successfully on port 8000的输出说明登录服务启动正常。如果报错把错误信息复制下来去搜一下绝大多数都能在网上找到答案。5. 服务端全流程启动与验证5.1 按启动顺序依次拉起各服务进程游戏服务端进程之间有依赖关系不是随便哪个先启动都可以的。常规顺序是数据库服务 - 登录网关 - 游戏逻辑服务 - 世界/地图服务。数据库没起来之前任何服务尝试连接数据库都会直接失败退出。按正确顺序执行# 第一步确认数据库在运行 systemctl status mysqld # 第二步启动登录服务 cd /data/game-server/login ./start.sh # 等3-5秒让登录服务连接好数据库 # 第三步启动游戏服务 cd /data/game-server/game ./start.sh # 第四步如果存在独立的world服务器再启动它 cd /data/game-server/world ./start.sh一次启动多个服务的场景我建议写一个总控脚本放在/data/game-server/start_all.sh里#!/bin/bash echo Starting login server... /data/game-server/login/start.sh sleep 3 echo Starting game server... /data/game-server/game/start.sh sleep 3 echo Starting world server... /data/game-server/world/start.sh echo All servers started.这样每次重启服务器后一键就能拉起全部服务省去逐个操作的麻烦。5.2 端口监听与进程存活检查方法服务启动后用两个命令验证服务是否真正跑起来了# 查看端口监听状态 netstat -lnpt | grep java # 查看进程状态 ps -ef | grep java如果端口处于LISTEN状态说明服务至少在监听。但监听不代表功能正常还需要检查日志# 查看服务日志的末尾部分 tail -n 100 /data/game-server/login/logs/login.log日志是最诚实的“发言者”。如果看到connection refused说明数据库配置或权限有问题看到Address already in use说明端口被占用看到OutOfMemoryError说明内存不够需要调整JVM参数。熟练掌握日志排查游戏服务端运维就学会了一大半。5.3 资源下载服务Nginx的连通性测试在修改客户端之前先确保资源服务器能被访问到。本机测试一下curl -I http://127.0.0.1/game_res/version.txt正常应该返回HTTP/1.1 200 OK。如果返回404检查Nginx站点配置如果连接拒绝检查Nginx是否在运行、防火墙是否放行了80端口。资源服务器不通的话客户端即使连上登录服务也会卡在检查更新或下载资源这一步。5.4 客户端连接地址修改与重新打包服务端全流程跑通后就到了客户端改造这一步。手游客户端一般是个APK或者APP安装包它内部会写死一个官方服务器地址。我们要做的是把它改成指向我们自己的服务器IP。由于每个项目的客户端打包工具链不同我这里只讲通用逻辑用apktool之类的工具反编译客户端安装包在资源文件中搜索域名或IP字符串通常是http://开头的地址可能存在于Config.ini、server.xml或AndroidManifest里把地址替换成你自己的服务器IP格式如http://你的IP:8080/login.php重新签名打包并安装这一步技术难度不高但比较繁琐。经验是搜索关键词不要只搜IP还要搜游戏名称的拼音缩写、项目代号等因为有些配置文件里的地址会被拆成多段拼接光搜IP搜不到。另外改完后记得用文本对比工具确认没有改漏其他跳转域名。5.5 进入游戏验证核心功能客户端安装完修改版之后打开游戏正常流程是输入账号密码 - 弹出服务器列表 - 选择测试服 - 创建角色 - 进入游戏地图 - 开始打僵尸。如果登录时报“服务器维护中”或“网络错误”优先检查数据库里的服务器列表配置是否填充正确——服务器名字哪怕少个字都会导致客户端解析失败。如果创建角色报错优先看游戏逻辑服务的日志报什么错。如果进去以后怪物不打你或者地图白屏那要检查世界/地图服务是否正常运行、资源文件是否完整同步到Nginx目录下。6. 常见问题与排错经验速查6.1 连接失败类问题我按照实际运维中出现概率排序整理了一份排查表现象可能原因排查方法客户端提示网络错误端口未放行检查云安全组和服务器防火墙规则登录后无服务器列表server_list表配置错误检查数据库里的IP和端口字段卡在获取资源100%Nginx目录权限或资源缺失检查html目录权限和文件完整性创建角色失败数据库表不完整对比脚本表结构与官方说明对照表进图后没有怪物world服务未启动查看world服务日志是否报错连接被重置服务端进程崩溃查看JVM日志和内存使用情况6.2 服务启动报错与日志定位技巧新手最容易犯的错是启动时看到一点报错就开始百度其实很多报错看一眼信息就知道怎么回事。比如ERROR: Failed to connect to database这就是数据库连不上。照着顺序查数据库启动了没 — 数据库账号密码对不对 — 配置文件里的IP端口对不对 — 防火墙有没有拦。Exception in thread main java.net.BindException: Address already in use端口被占用。用lsof -i:8000找出占用端口的进程要么干掉它要么改配置文件换一个端口。OutOfMemoryError: Java heap space内存不够。调整JVM参数改成java -Xmx4g -jar game.jarXmx后面的数字代表最大堆内存按服务器实际内存来定别超过物理内存的70%。排错的大原则是从下往上查。先查基础设施数据库、网络、端口再查服务进程启动顺序、内存最后查配置细节IP、密码、表数据。跳过基础设施直接改代码逻辑往往是白费功夫。6.3 系统重启后的自启动配置测试服最怕什么最怕机房断电重启后MySQL和游戏服务没有自启动导致玩家全部掉线、登录不上。所以服务器重启后的自动拉起一定要配置好。# 把start_all.sh加入rc.local实现开机自启 echo /data/game-server/start_all.sh /etc/rc.local chmod x /etc/rc.local另外还要把MySQL和Nginx设置成开机自启前面已经用systemctl enable配置过了。为了验证自启动配置是否生效建议重启一次服务器实测宁可现在发现配置失败也不要等开服时才发现。6.4 我建议你保留的几个调试命令一直在用且几乎每次排错都能用上的命令就下面这几条建议直接存进笔记# 实时查看日志排查在线问题 tail -f /data/game-server/game/logs/game.log # 检查端口监听 lsof -i:8000 -i:8001 -i:3306 # 测试数据库连接 mysql -ugame -p -h127.0.0.1 game_db -e select 1 # 查看内存占用 free -h # 查看进程资源消耗 top -p 进程PID熟练用这些命令基本能应对日常90%的故障排查场景。配上日志关键字检索比如grep ERROR效率还能再翻一倍。7. 延伸玩法与进阶优化建议服务端一旦跑通这台“私服”能玩的花样比想象中多。下面几个方向是我后来逐步摸索出来、觉得很值得做的扩展玩法说白了就是用好手头的服务端和数据库让这套环境不只是一个能登录的游戏壳子。调整游戏经济数值做私服化运营把掉落率、经验倍率、初始资源等参数调出一个“高倍率服”的体验配合数据库定时发邮件、发物资的脚本就能做出一个活跃度很高的测试生态。这一步不需要改代码只要把数据库里跟经济系统相关的存储过程、事件调度器利用起来就够。做GM后台很多服务端源码会自带管理命令或者简单的GM工具把这些命令接出来做成一个网页端的操作界面就能实现发装备、封号、公告、全服通知等操作。工具按顺序做起来运维会轻松很多。做监控告警定时监控游戏进程在不在、端口通不通、日志有没有异常关键字发现异常推个通知出来不需要买商业监控平台写个shell脚本加crontab定时任务就够用。做数据统计分析通过定期抓取数据库里的玩家表、流水表统计在线峰值、留存率、消费排行榜等指标做成简单的图表。这套环境就是你学习数据分析和游戏运营最好的练手场。扩展多人联机场景如果朋友都来连你的服务器IP是公网IP那要注意带宽和服务器负载。测试阶段还好真要长时间开服就得考虑带宽扩容和CPU优化了比如把数据库单独拆分到另一台机器。我个人在这些扩展中最推荐先做GM后台和监控告警因为这两个直接提升你运维这套环境的体验和安全系数。其他方向可以等基础稳定之后再一步步加。说到底手工搭建服务端最有价值的地方不在于“跑起来”那一瞬间的快感而是跑起来之后你能顺手掌握数据库操作、Linux运维、网络排错、游戏逻辑调整这一整套技能。最后再分享一个我踩过多次坑之后的习惯每次修改配置文件或数据库数据之前先做备份。配置文件直接cp一份加上日期后缀数据库就用mysqldump导出一下。游戏服务端里很多问题就是因为调试时随手改了个参数、忘了改回来导致线上环境出诡异故障。备份成本极低但能救命的次数多得数不过来。搭建这件事稳字永远是第一位的。
返回列表