Answers:
尝试使其尽可能简单,并明确定义和记录接口。在生产中维护和调试复杂的系统很容易陷入困境。因此,如果有一种简单而又复杂的方法,那么在使用复杂方法之前,请三思而后行。
我认为第一步是识别服务及其依赖项:静态内容,身份验证,本地聊天,全球聊天频道,区域聊天频道,朋友列表,公会,行李/库存,拍卖行,全球地图,世界,...
然后针对这些服务中的每一个,确定客户是否可以直接与他们交谈。例如,让客户直接与负责全球聊天频道的服务器对话很容易。世界服务器根本不必参与聊天消息。区域聊天可以以相同的方式实现,但是当玩家更改区域时,世界服务器必须告诉聊天服务器。同样,他们不必关心消息。
第三步是考虑服务内的负载平衡。例如,全球和区域聊天频道可以根据其名称分布在多个服务器上。最好不要将这些内容硬编码到客户端中,而要提供查找服务。
最困难的部分通常是世界服务器,所以我从一个简单的方法开始。让客户端直接与负责其所在区域的服务器通信可能是一个好主意。因此,在登录或穿越区域时,必须告知客户端要连接到哪个服务器。
简单的方法是将世界分成独立的区域。对于独立区域,我的意思是玩家不能从一个部分看向另一部分,而怪物也不能越过部分。这些区域与玩家根据外部环境和故事所看到的区域不同。通常,大多数怪物都在地牢中,玩家倾向于接受它们必须走过进入地牢的通道。特别是如果这些地牢是按每个玩家组实例化的。外部世界的其他示例是被高山包围的不同大陆和山谷。
一个连续的世界的方式变得复杂真的很快,所以是有意义的计划得好:信息做什么客户需要什么?服务器必须共享哪些信息?玩家通常只会与同一地区的物体(包括怪物和NPC)互动。您可以通过将对象放置在区域边框的单击范围之外来作弊。这意味着客户端最感兴趣的是邻近区域的只读信息。在这些情况下,区域服务器无需进行任何协调,除了权限检查,即播放器是否足够近以可以连接到相邻区域。
这仅留下了极少数的困难情况,其中对象或动作必须跨越服务器边界。这是一件好事,因为箭头和咒语等情况对性能至关重要。将战斗分为攻击和防御可能是个好主意。因此,施法者的服务器将定义攻击参数,包括施法者的位置。防御者的服务器将获得有关攻击的消息并计算影响。攻击者的服务器不需要知道影响;客户将使用其只读连接来了解它。
根据播放器模型的复杂程度,可能需要花费几秒钟的时间才能将其传输到另一台服务器(《第二人生》对此存在巨大问题)。当玩家接近虚拟边界时,可以通过预先准备转移来缓解此问题。这样,当实际切换发生时,大多数播放器数据已经缓存在目标服务器上。
通过定义可以在几乎没有依赖性的情况下跨服务器拆分的不同服务来划分问题。下一步研究如何在关键服务中实现负载平衡。通过指示客户端直接连接到相关服务器(显然,服务器必须检查权限)来将平衡工作委托给客户端。使其尽可能简单,很好地记录各种服务和服务器的职责,并提供启用调试输出的选项。
PS:这些技术中的一些可以用来提高可靠性。您应该牢记这一点,因为使用许多服务器意味着发生故障的风险要高得多。不仅在软件方面,而且在硬件方面。
通常,世界分为多个较小的区域。这些区域中的每个区域通常是一个独立的服务器进程(WoW的世界服务器或Eve的Sol节点),并且可以在许多计算机上运行。在某些游戏中,地图之间存在明确的门(前夕,STO,激战),而其他游戏则试图掩盖更多信息(战争,自由境界)。那些选择更无缝方法的服务器通常会检测到您何时接近两个服务器之间的边界,并且两个进程协商越区切换。可能需要对此进行描述的最佳位置是蜂窝塔如何完成移动手机的越区切换。如果单个地图(Jita,Ironforge,Earth Space Dock)的负载真的很大,有时您可以将单个功能卸载到其他服务器(AI,播放器管理的某些部分),但这要么必须从一开始就内置,要么要进行认真的改装。仅仅购买更好的硬件以专用于那几张地图,几乎总是更具成本效益的。
我相信MMO的普遍要求是,可以在多台服务器上完成单个分片或领域的处理,以减轻负载。我很好奇如何在保持所有玩家和所有NPC可以互动的统一一致世界的同时完成此工作。
它可能不如您想像的那么普遍。至少,如果您认为一个无缝世界由多个服务器同时管理,则不是这样。
不计算完全独立的碎片,您可以从两个方向分解在线游戏,可以将其视为“水平”和“垂直”:
显然,这些方法是正交的,您可以将两者结合起来。实际上,拥有一个单独的数据库服务器几乎是强制性的,无论在游戏世界中如何,将登录/身份验证从游戏中分离到另一台机器上都是很常见的,并且从聊天和其他非关键性通信中获得农场也越来越普遍划分。
但是总的来说,当进行地理划分时,大多数游戏都避免让您跨越这些边界进行交互,因为这样做很难。相反,他们求助于其他方法,使您看起来好像都还处在同一分片和同一服务器上,而实际上却不在。例如。-在区域之间或从一个大陆到另一个大陆过渡时,加载掩盖服务器的屏幕或其他动画会发生变化。-与其他人隔离的独立地牢或团队副本实例。这些就像分片中的分片一样,可以轻松地在单独的服务器上运行,从而有助于负载平衡。
我无法在《魔兽世界》上与权威人士交谈,但我想他们几乎可以完成上述所有工作:实例化,无法交互的单独地理区域,某种类型的门户,单独的后端服务器和身份验证服务器。我听说《魔兽世界》领域一次在给定领域中在线拥有1000至10000名玩家,这可以通过上述方案轻松管理。
但是,假设您拥有一个庞大的世界,并且确实需要允许玩家使用一台服务器与相邻服务器上的玩家进行交互。从理论上讲这很容易-首先,服务器必须合作以沿边界共享对象的详细信息(因此一台服务器上的对象可能在另一台服务器上具有代理表示),然后只需将所有逻辑更改为消息传递即可,必要时将邮件从代理路由回权威源。消息可以在服务器之间或服务器内透明地传递,因此一种方法适用于所有系统。
这里的问题是,以前简单的逻辑在转换为消息时会变得非常复杂。当两个玩家都在一台服务器上时,可以安全,原子地进行的两个玩家交易将变成一个较长的过程,这时必须来回发送消息,每次发送都要重新验证,并且采取了安全措施以确保一个玩家无法利用另一种方法是在消息传播时更改交易。您甚至无法假设消息到达时其他播放器仍然存在(因为它们可能会死掉,注销等),因此代码变得非常复杂。这几乎适用于两个或两个以上实体可以交互或合作的任何系统-贸易,战斗,分组,拍卖,战利品共享,培训等。
这些问题并非无法解决,但对于大多数游戏而言,当您可以通过其他方式分担负载并将所有游戏逻辑都保存在一台服务器上时,就很难尝试。因此,几乎所有当前的游戏都顺其自然。
有多种负载均衡MMO服务器的方法,因为要处理的数据范围很广。我更喜欢进程树树方法。
全局服务器将用户连接传递到可同时处理多个用户的处理仓。处理容器执行所有复杂的处理,并且仅使用全局相关的数据(例如全局聊天和定位)响应全局服务器。这种方法比区域服务器的平衡要好得多,因为区域的人口可以有很大的不同,而整个用户的处理过程却变化很大,因此它自然可以在大多数情况下实现自身的平衡。
只需通过全局服务器执行一些基本的负载平衡,以便当流程容器达到一定的内存/ CPU使用率时,就可以启动新的流程容器服务器。