共计 3563 个字符,预计需要花费 9 分钟才能阅读完成。
课程简介
本课程为机械工业出版社出版的图书《百万在线:大型游戏服务端开发》的电子版。
第一局部:学以致用(第 1~4 章),这部分介绍了 Skynet 引擎的应用办法及注意事项,以《球球大作战》的案例贯通其中,全面又详尽地分析了服务端结构设计、通信协议格局、数据表结构设计、断线重连等计划的核心技术。
第二局部:入木三分(第 5~7 章),这部分揭示了在多核时代采纳古代 C ++ 编写多线程 TCP 网络服务器的高效做法,以 C ++ 重写 Skynet 的案例贯通其中,应用大量图表,活泼翔实地形容 Linux 环境下的编程技术。
第三局部:各个击破(第 8~11 章),这部分列举了同步算法、热更新、防外挂等理论工程难题,并对其逐个击破,十分具备实用价值。只管本书以 Skynet 为例,但其同样实用于应用 C ++ 自研引擎的项目组,甚至是选用 Erlang、Golang、Java 的开发者。
关键词:
C/C++/Lua | Socket、TCP/IP、Protobuf | Linux 开发环境 | 多线程、数据库、分布式 | 高并发、内存透露、热更新
残缺版本,能够返回 UWA 学堂查看《百万在线:大型游戏服务端开发》。
第 1.1 节 咱们简略介绍了从玩家的角度来看,一款网络游戏大都会波及的流程,在此过程中,藏在幕后的服务端做了很多事件,那到底做了哪些?此服务端零碎又是如何开发的呢?
服务端程序要承载很多玩家,性能是必须要思考的问题。那么,1.2.4 节的程序可能承载多少玩家同时在线呢?
1.3 大节介绍服务端程序要承载很多玩家,性能是必须要思考的问题。
对于中大型商业游戏来说,往往呈现全服爆满的景象(如图 1 -12),1000 多人的承载量远远不够。依据游戏厂商的新闻稿可知,2012 年《梦幻西游》最高同时在线玩家达到了 270 多万人;2016 年《王者光荣》的同时在线玩家超过了 300 万人。既然单个程序的承载量无限,最间接的方法就是开启多个程序来进步承载量。
图 1 -12 玩家爆满的游戏画面示意图
1.4.1 多个程序协同工作
图 1 -13 展现了一种由多个程序独特合作的服务端模型,图中程序 A 和程序 B 别离解决客户端音讯,程序 C 作为中转站,负责程序 A 和程序 B 之间的通信。每个程序均独立运行,能够将其部署在不同的物理机上,造成人造的分布式系统。
图 1 -13 多过程服务端示意图
阐明:为对立术语,本书中“服务端”代表整个游戏服务端零碎;“程序”“过程”或“节点”代表一个操作系统过程;“物理机”代表服务器,涵盖了实体服务器和云服务器。
只管单个程序还是最多承载 1000 余人,然而只需开启 1000 个程序,并将其安排在数百台物理机上,实践上就能够撑持 100 万玩家,总承载量得以进步。
1.4.2 三个档次的交互
在分布式构造中,数据的交互被分成了三个档次,如表 1 - 2 所示。这就要求开发者能对游戏业务性能做出正当的切分。在游戏中,有些性能是强交互的,有些性能是弱交互的。以 MMORPG 为例,同一个场景的角色交互很强,每走一步都要让对方晓得,能够在同一个程序中解决同一个场景逻辑;不同场景的角色交互较弱,只有聊天、好友、公会这些性能须要交互,能够将同一个服务器的玩家都放在同一台物理机上解决;不同服务器的玩家交互很少,能够放到不同的物理机上。
表 1 -2 不同交互场景的区别
1.4.3 搭个简略的分布式服务端
实践归实践,实际出真知。实现 1.2.4 节的“走路”程序是场景服务器的一项次要性能,只管一个场景只能撑持数十人,只有多开几个场景就可能反对更多玩家。本节将实现图 1 -14 所示的分布式程序,零碎中有两个“走路”程序,别离代表兽人村落和森林两个游戏场景,客户端间接连贯角色所在的场景,玩家只能看到所在场景的角色,不同场景角色能够全服聊天。该程序可分成三个步骤实现。
图 1 -14 简略的分布式系统
第一步,编写聊天服务器。聊天服务器其实是转发服务器,它治理着场景服务器发来的连贯(见代码 1 - 5 中的 scenes),只有收到场景服务器的音讯,它就会播送给所有的场景服务器。聊天服务器会监听 8010 端口,期待场景服务器连贯。
代码 1 -5 聊天服务器(Node.js)
(资源:Chapter1/3_chat_server.js)
var net = require('net');
var scenes = new Map();
var server = net.createServer(function(socket){scenes.set(socket, true) // 新连贯
socket.on('data', function(data) { // 收到数据
for (let s of scenes.keys()) {s.write(data);
}
});
});
server.listen(8010);
第二步,让场景服务器(“走路”程序)连贯聊天服务器。场景服务器即是服务端又是客户端,对于玩家来说,它是服务端,对于聊天服务器来说,它又是客户端。在“走路”程序的根底上,让场景服务器连贯聊天服务器(见代码 1 - 6 中的 net.connect),当场景服务器收到聊天服务器发来的数据时,就会把它一成不变地播送给客户端。
代码 1 -6 场景服务器的局部代码,用于连贯聊天服务器(Node.js)
(资源:Chapter1/3_walk_server.js)
var net = require('net');
//"走路" 程序略 server.listen(8001);
var chatSocket = net.connect({port: 8010}, function() {});
chatSocket.on('data', function(data){for (let s of roles.keys()) {s.write(data);
}
});
第三步,给场景服务器增加聊天性能(见代码 1 -7)。假如客户端除了发送“left”“right”等指令外,还会发送聊天文字,那么在收到聊天音讯后它会把音讯原样发给聊天服务器。整个音讯流程是:①场景服务器将聊天音讯发送给聊天服务器;②聊天服务器把音讯播送给所有场景服务器;③各个场景服务器别离将聊天音讯播送给场景中的所有玩家。
代码 1 -7 场景服务器解决聊天音讯的局部代码(Node.js)
(资源:Chapter1/3_walk_server.js)
// 接管到数据
socket.on('data', function(data){
……
// 更新地位
if(cmd == "left\r\n") role.x--;
……
else {chatSocket.write(data);
return;
};
……
});
当初能够进行测试了,先运行聊天服务器,再顺次运行两个场景服务器(假如监听的端口别离为 8001 和 8002)。如图 1 -15 所示,客户端 A 和 B 连贯第一个场景服务器,客户端 C 连贯第二个场景服务器,服务器中的小方块代表各个程序,方块中的数字代表该程序的监听端口。当客户端 A 走动时,因为 A、B 同在一个场景中,所以它们会收到挪动音讯,而客户端 C 不在同一场景中,因而它不会收到;若客户端 A 发送聊天信息“战神公会招人”,三个客户端都能收到。
图 1 -15 测试分布式服务端
1.4.4 一致性问题
分布式程序要解决很多异常情况。如果程序部署在不同物理机上,连贯不太稳固,须要解决好断线重连、断线期间的音讯重发,以及断线后过程间状态不统一的问题。图 1 -16 展现的是因网络不畅通导致的异样情景,如果客户端 A 的玩家向客户端 B 的玩家购买道具,音讯须要通过程序 C 直达,因程序 A 和程序 C 之间的网络连接出现异常,呈现了客户端 B 的玩家被扣除了道具,客户端 A 的玩家却没失去道具的状况。程序 A 与程序 C 的网络连接异样,游戏性能受到了影响,就算一段时间后从新连贯上,两个过程的状态也可能会不统一。
图 1 -16 分布式程序的异样情景
一致性问题是分布式系统的一大难题,在游戏业务中,开发者个别会把一致性问题抛给具体业务去解决。对于图 1 -16 所示的异常情况,须要给每个交易赋予惟一编号。程序 C 除了转发音讯,还须要记录程序 A 对每个交易的执行状态,如果转发失败,程序 C 要在稍后重发交易音讯,直到程序 A 胜利执行。而程序 A 也须要记录每个交易的状态,如果某个交易曾经胜利执行,则不再响应程序 C 发来的音讯,防止反复增加道具。
另外,治理数百台物理机、成千盈百个程序也不容易,第一,物理机多了,某一台出故障的可能性很大;第二,开启或敞开全副程序要花费很长时间。
本篇为《百万在线:大型游戏服务端开发》其中局部内容,残缺版本能够返回 UWA 学堂查看。
适宜读者
1、刚入行的服务端工程师
2、游戏公司开发岗位的求职者
3、对游戏开发感兴趣的高校学生
4、游戏开发爱好者
你将取得
1、充沛理解业务逻辑和底层框架的设计用意
2、立足实际的服务端学习思路,深入浅出
3、用理论案例贯通各知识点,在实践中学习
4、理解商业游戏的设计思路和实现办法