为什么王者荣耀、原神等游戏不使用微服务架构?

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 王者荣耀、原神作为家喻户晓的手游,能够支撑这么多人同时在线,其底层的架构自然令我们好奇,出乎意料的是,它并没有采用目前炙手可热的微服务架构,到底为什么会这样呢?本文结合知乎问答内容:https://www.zhihu.com/question/359630395撰写,本人其实也是个游戏迷,这次也是想深扒一下其底层的架构设计。

微服务架构

这段是背景引入,了解的大佬可以直接跳到后面。

基本概念

微服务最主要的功能是根据业务拆分成一个一个的子服务,实现功能的去耦合,每一个微服务提供单个业务功能的服务,各司其职,从技术角度看就是一种灵活独立的单元,能够自行单独启动和关闭,一般每个服务都拥有自己的数据库模块。

在传统的IT行业软件大多都是各种独立系统的堆砌,这些系统的问题总结来说就是扩展性差,可靠性不高,维护成本高。到后面引入了SOA服务化,但是,由于 SOA 早期均使用了总线模式,这种总线模式是与某种技术栈强绑定的,比如J2EE。这导致很多企业的遗留系统很难对接,切换时间太长,成本太高,新系统稳定性的收敛也需要一些时间。最终 SOA 变得很笨重,在一些中小企业的场景中并不适合。

微服务与单体架构区别

单体架构所有的模块全都耦合在一块,代码量大,维护困难,微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比较好解决。 单体架构所有的模块都共用一个数据库,存储方式比较单一,微服务每个模块都可以使用不同的存储方式(比如有的用redis,有的用mysql等),数据库也是单个模块对应自己的数据库。 单体架构所有的模块开发所使用的技术一样,微服务每个模块都可以使用不同的开发技术,开发模式更灵活。

微服务和SOA的区别

微服务,从本质意义上看,还是 SOA 架构。但内涵有所不同,微服务并不绑定某种特殊的技术,在一个微服务的系统中,可以有 Java 编写的服务,也可以有 Python编写的服务,他们是靠Restful架构风格统一成一个系统的。所以微服务本身与具体技术实现无关,扩展性强。

微服务的特点

微服务的主要作用在于实现了一套基础架构系统,使得各个服务之间松耦合,在功能上表现为统一的整体。这种所谓的“统一的整体”表现出来是统一风格的界面、权限管理、安全策略、上线过程、日志和审计方法、调度方式和访问入口等等。

微服务设计原则

单一职责原则 每个微服务只需实现自己的业务逻辑,比如教学模块,它只需要处理教学相关业务逻辑就可以,其它的内容拆分出去;

服务自治原则 各个微服务从开发、测试、发布、运维等都是彼此独立的,他们的存储数据库也彼此分开,降低了各自的依赖;

轻量级通信原则 首先是彼此通信的语言非常的轻量,其次是通信方式需要跨语言、跨平台,这是为了让每个微服务都有足够的独立性,可以不受技术的限制。常见的方式是通过REST API或RPC的方式进行通信;

接口明确原则 一般微服务之间会存在调用关系,为了尽量避免某个微服务的接口变化而导致其它微服务牵一发而动全身,在设计之初就要考虑到常用的情况,让接口尽量做到通用灵活,尽量避免大范围的改动。

游戏公司为什么不使用微服务架构?

这里我想引用几个知乎大佬们的回答,可以给我们带来很多启发和思考:

陈宏基的回答

比如 moba 类游戏/王者荣耀/LOL,就看王者荣耀的客户端吧,想象一下。

账号系统,符文系统,英雄系统,皮肤系统,好友系统,好友之间 messaging,这些都是常规操作,如果流量足够大,当然可以用微服务的架构去做。

不过这不是这个游戏的核心,核心是 MOBA:Multiplayer online battle arena。特性是什么?

10 个人之间各种游戏事件的高速多向通讯 streaming/broadcast/multicast/pubsub 各种通讯模式

所以游戏的核心在于小规模群体之间的高速网络通信 。就是对方说的 realtime。多了一个 10ms 的延迟玩家就要骂娘了。

  1. 微服务为了把业务完美拆解,把原来的同一个进程里的模块拆分成不同的服务,显著增加额外的网络开销 。更别说什么 service mesh,各种 gateway,proxy,sidecar,简直就是担心延迟太低。

  2. 微服务基本只有 request/response 的模式。做不了 streaming?微服务通常要求应用是无状态的才能做到水平扩展。streaming 本身就是加入了状态。

  3. 我可以想像,为了提高通讯的性能,一场英雄联盟游戏很可能会使用同一个服务器负责这 10 个玩家之间的通讯,这样就使得数据可以在本地交换,性能最大化 。这对客户端或者说服务端统一网关的要求是必须支持 sticky routing。假设客户端连接断了,接下来的必须重连之前的同一个服务器。微服务的 stateless,水瓶扩展要求本身就是反 sticky routing 的,因为 sticky routing 本身就是状态。

  4. 对服务端集群来说,同时有无数个王者荣耀的比赛在进行,每个都可以看成一个沙盒,每个沙盒都处于一个不同的状态:塔被推了几个了,你被杀了几次了,对面几个超神了,20 分钟到了没。这些都是长时间存在的状态,直到游戏结束,服务端才可以清理一场游戏的状态。
    所以虽然不用把这些状态写进持久性存储,但是必然会在内存中存在很长时间。都是状态,反正有状态,就别想用微服务。除非你说把这些状态都移到 redis 里去,那么在服务器在信息流传输到一半还要做一个 remote request,一来一回,延迟就上升了。总之怎样都不好。(比如想象对方在 A 你的水晶,每一次 A 的操作都是一个 event,被 streaming 到服务端的沙盒中,沙盒中有一个流处理器,每次接收到一个你水晶被 A 的 event 都会计算一下你水晶爆了没。这个计算需要极快,你是不可能把你水晶生命值的数据存在远端的)

像这类游戏,都是对网络,内存,CPU 的优化需求很高,整个游戏进行过程中,几乎不存在什么 RPC call,真的需要 remote data,也应该是 prefetch,就是在游戏刚开始的时候加载好

微服务不是什么银弹,也就是方便拆解一下原来的 CRUD 应用罢了而已,一没触及高级的交互方式,二没触及分布式系统真正的难点:状态,其实没有大家想的那么有用。之所以感觉上好像微服务改变了互联网,只不过 90%的互联网应用都只是简单小规模的 CRUD 而已。

对方没有听说过微服务完全没有问题,因为这本身就不是什么高深的概念,反而对方听你一说一下就知道微服务不适合游戏,说明对方理解能力很强,对游戏系统设计也了解足够深。



码农在新加坡的回答

这世上没有通用的架构,所以不要觉得微服务很牛逼。微服务还真的不适合游戏开发。因为游戏大多是有状态的,而且是低延迟。微服务业务拆分,很适合无状态的普通服务器。跟你说一下游戏服务器和普通服务器的区别你就知道为什么了。

互联网和游戏后端开发的区别

游戏特有的:

  • 保持连接:游戏一般来说需要保持一个客户端到服务端的连接,可以对客户端的玩家的行为(移动,攻击,操作,互动,聊天)进行及时的反馈以及主动推送给相关的玩家。所以游戏更多的使用TCP来保持客户端和服务端的连接,少量游戏会使用UDP或者HTTP。

  • 保持状态:服务端会保持一份玩家的实体,当玩家进行操作时,下次通信的数据会依赖之前的通信的数据。主动推送:游戏服务器由于保持连接和状态,任何数据的改动可以通过服务端主动通知客户端的方式,这样就只需要推送修改的数据。不需要客户端频繁去刷新。

  • 低延迟:很多游戏服务器,尤其是 RPG,MOBA, FPS等游戏,对延迟容忍度非常低,网络拥堵情况下tcp协议由于重传机制,拥塞机制导致非常慢,就需要重新设计协议来处理。

  • 写频繁:游戏中的每一个操作都可能是一个数据,移动、攻击、交易、经验增长等等,所以游戏通常来说需要定时写数据,否则可能会有DB性能瓶颈。

  • 互动:很多游戏是多人游戏,需要玩家互动,这个时候需要保持任何玩家之间都能及时的互动或者沟通,对服务器架构上的设计就有一定的要求,互联网的很多业务分离的微服务架构,很难让所有的玩家能及时的沟通。

  • 复杂度高:由于游戏大多数是交互的,所以做游戏后端开发的业务复杂度比互联网是高的,互联网主要是增删改查(高并发下也挺复杂,但是主要是性能复杂度)。但是游戏却是业务复杂度。比如,你做一个战斗系统,回合制(梦幻西游)的战斗系统怎么做,怎么保存交互的状态,Moba(王者荣耀)的战斗系统怎么做,怎么处理每一帧的指令。

  • IO密集型:游戏大多数是IO密集型的,它的主要瓶颈在网络/磁盘IO,而不是CPU。因为游戏很多多人在线,相互之间同步的数据导致整体的IO非常高。因为CPU并不高,导致很多时候都不需要多线程。

互联网特有的:

  • 请求响应:互联网应用一般只需要支持请求响应式的通信,最常用的协议是HTTP来做客户端和服务端的通信。互联网应用一般来说只用关心自己的行为,而不太关注其他用户的行为(即使关注,也没有ms级别的响应要求),所以一般来说即使需要读到其他用户的数据,只需要刷新一下页面就好,也不需要服务端实时推送。

  • 无状态:互联网的应用一般是无状态的,也就是每次进行不同的操作,都需要服务端进行完整的数据读取操作,无法利用上次请求的数据。

  • 服务拆分:互联网是比较容易做服务拆分的,因为业务相对独立,交互弱,做成微服务架构,依赖关系用网络请求来请求数据。一个很长的调用链拿到所有数据。

  • 读频繁:互联网一般是一个读频繁的场景,需要大量的读取数据,只有特定的行为才需要写入。要考虑一定的缓存机制,对数据库的设计要求更高。

  • 延迟容忍:可以容忍一定的延迟,100ms和10ms对用户的体验影响并不大。

  • 增删改查:互联网说到底就是增删改查。(当然1000用户的增删改查和10亿用户的增删改查不一样)。我现在处理十亿级数据千万级QPS的服务。主要考虑高并发下的服务的拆分,架构的设计,微服务化,数据拆分,缓存设计,异步存储,热点处理等等一系列高并发下的性能考虑。但是仅仅业务本身的复杂度相对游戏较低低。

  • CPU密集型:互联网的服务器大多是CPU密集型的。业务层涉及到大量的数据计算。你看,是不是感觉差别天差地别。同时,游戏服务器特有的很多特性,在微服务上实现,复杂很多。

同时,游戏服务器特有的很多特性,在微服务上实现,复杂很多



某知乎用户的回答

做过棋牌游戏(游戏最简单的一种),可以尝试说几个点:

  1. 微服务本身是为了应对业务逻辑的复杂,需要要的新的组织接口的方式。游戏本身逻辑其实没有这么复杂,比如大厅就是一些基本功能,修改帐号,登录等。游戏本身就是游戏本身的逻辑。

  2. 游戏逻辑服务器本身(比如斗地主等棋牌)因为网络响应性能要求问题(玩家对每个操作的反馈时长敏感度远高于业务系统),所以游戏服务器都是有状态的,状态就存在内存,偶尔会接受redis,mysql等是绝对不可以的接受的,关系行数据库仅用来定时异步持久化数据,仅游戏服务器而言持久化在redis即可。

  3. 游戏服务器一般纯需要主动推送,所以第一代微服务网关就没办法满足需求, tcp的没有网关用,spring cloud gateway的web socket也许可以用(但是从防攻击角度讲端游用TCP绝对比web socket合理)。

  4. 服务间通信rpc首先ribbon,feign等并不是合适,因为都是基于http的,用Http存在一个消息乱序问题,比如玩家出牌两次,在http就可能出现次序不一致。游戏服务器集群一般使用长连接互联。可能需要用dubbo?(听说是长连接)

  5. 游戏逻辑服务器(比如斗地主服务器),一般是不能用spring mvc做的,因为线程模型完全不同。多线程模型处理游戏性能差还非常复杂,一般都是使用单进程/线程 驱动固定数量房间的方式(这也是为何服务器一定有状态,一定不能直接读写mysql)。一般就直接netty了

  6. 自动扩容在游戏这边叫做开服,早就有固定流程和工具和限流方式了

  7. 游戏很多操作不存在服务降级熔断,不行就要直接报错给用户。

  8. 大厅服务器登录注册等的确可以做微服务,但是其实也不是做微服务,就是几个接口有自动水平扩容的方案即可。服务注册发现用处不大,开服都是确定的事情,还有一系列运营手段配合,关服也是绝对不能随便关的。

  9. 游戏处理的流量真的不算多,你在线1万的棋牌游戏已经很赚钱了,10W就是个特别厉害的产品了。

  10. 一些独立的服务器比如充值之类的需要微服务化么?只能说这种服务器都需要微服务处理了,项目组做梦都能笑醒。

虽然上面说了很多点,但是其实也是可以考虑用spring cloud改造的,因为游戏集群一样有注册中心,需要服务发现,需要编排启动顺序,只是spring cloud没有为了游戏设计而已,比如至少要完全支持 webflux吧(没有仔细研究),需要一个单线程的长连接最好支持protobuf rpc框架吧(集成服务发现相关功能与接口),网关支持tcp或者至少封装或者暴露一些netty的decoder encoder(或者允许注入)等等skynet等不在讨论范围之内。

个人看法

首先抛出观点:微服务应该是业务能力的拆解,不是功能的拆解。比如说王者荣耀里面,其实对战系统、商城系统、聊天系统等从理论上来说已经满足是拆分之后的单个服务的,至此,虽然没有实际采用微服务架构但是其理论上依然满足微服务的说法。

再其次,如果采用微服务架构,那么从性能和延迟、复杂性和维护成本、数据一致性、开发效率和资源利用率等方面来说就需要多做一些考虑了。

  1. 性能和延迟:游戏需要实时响应,并提供流畅的游戏体验。微服务架构引入了网络通信的开销,可能会增加延迟并降低性能,这对于需要高速响应的游戏来说是不可接受的。

  2. 复杂性和维护成本:微服务架构涉及到拆分应用为多个独立的服务,每个服务都需要独立进行开发、测试、部署和维护。这增加了整体架构的复杂性,并且需要更多的人力资源来管理这些服务,这可能会增加开发和运维的成本。

  3. 数据一致性:游戏中的数据通常需要保持一致性,例如玩家的装备、道具、任务进度等。微服务架构中,不同的服务可能会有自己的数据存储和管理方式,确保数据的一致性变得更加困难。游戏公司可能更倾向于使用单体架构中的共享数据库,以确保数据一致性和简化数据管理。

  4. 开发效率:游戏开发周期通常紧凑,需要高效的迭代和快速的发布。微服务架构可能会增加开发和测试的复杂性,并且需要更多的集成测试和部署工作。单体架构在这方面更容易管理,可以提高开发效率和快速迭代的能力。

  5. 资源利用率:微服务架构通常需要运行多个独立的服务实例,这可能导致资源的浪费。对于大规模的在线游戏,需要考虑服务器硬件资源的有效利用以支持大量玩家同时在线,单体架构可能更容易实现资源的优化分配。

目前来看,微服务更多的还是用在web系统、大型互联网应用、电子商务平台、金融科技系统等方面在,越是体量大的,复杂度高的,异构型强的就越适合采用微服务架构。所以啊,虽然这个技术火热,但是也万万不可迷信它啊!

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
16天前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
16天前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
1天前
|
消息中间件 负载均衡 Cloud Native
云原生之旅:从容器到微服务的架构演变
在数字化转型的风潮中,云原生技术以其灵活性、可扩展性和弹性而备受青睐。本文将通过一个虚拟的故事,讲述一个企业如何逐步拥抱云原生,实现从传统架构向容器化和微服务架构的转变,以及这一过程中遇到的挑战和解决方案。我们将以浅显易懂的方式,探讨云原生的核心概念,并通过实际代码示例,展示如何在云平台上部署和管理微服务。
|
18天前
|
JSON 监控 安全
探索微服务架构中的API网关模式
【9月更文挑战第22天】在微服务架构的海洋中,API网关如同一位智慧的守门人,不仅管理着服务的进出,还维护着整个系统的秩序。本文将带你一探究竟,看看这位守门人是如何工作的,以及它为何成为现代云原生应用不可或缺的一部分。从流量控制到安全防护,再到服务聚合,我们将一起解锁API网关的秘密。
|
28天前
|
运维 Cloud Native Devops
云原生架构的崛起与实践云原生架构是一种通过容器化、微服务和DevOps等技术手段,帮助应用系统实现敏捷部署、弹性扩展和高效运维的技术理念。本文将探讨云原生的概念、核心技术以及其在企业中的应用实践,揭示云原生如何成为现代软件开发和运营的主流方式。##
云原生架构是现代IT领域的一场革命,它依托于容器化、微服务和DevOps等核心技术,旨在解决传统架构在应对复杂业务需求时的不足。通过采用云原生方法,企业可以实现敏捷部署、弹性扩展和高效运维,从而大幅提升开发效率和系统可靠性。本文详细阐述了云原生的核心概念、主要技术和实际应用案例,并探讨了企业在实施云原生过程中的挑战与解决方案。无论是正在转型的传统企业,还是寻求创新的互联网企业,云原生都提供了一条实现高效能、高灵活性和高可靠性的技术路径。 ##
52 3
|
1月前
|
监控 负载均衡 应用服务中间件
探索微服务架构下的API网关设计与实践
在数字化浪潮中,微服务架构以其灵活性和可扩展性成为企业IT架构的宠儿。本文将深入浅出地介绍微服务架构下API网关的关键作用,探讨其设计原则与实践要点,旨在帮助读者更好地理解和应用API网关,优化微服务间的通信效率和安全性,实现服务的高可用性和伸缩性。
44 3
|
1月前
|
存储 Java Maven
从零到微服务专家:用Micronaut框架轻松构建未来架构
【9月更文挑战第5天】在现代软件开发中,微服务架构因提升应用的可伸缩性和灵活性而广受欢迎。Micronaut 是一个轻量级的 Java 框架,适合构建微服务。本文介绍如何从零开始使用 Micronaut 搭建微服务架构,包括设置开发环境、创建 Maven 项目并添加 Micronaut 依赖,编写主类启动应用,以及添加控制器处理 HTTP 请求。通过示例代码展示如何实现简单的 “Hello, World!” 功能,并介绍如何通过添加更多依赖来扩展应用功能,如数据访问、验证和安全性等。Micronaut 的强大和灵活性使你能够快速构建复杂的微服务系统。
64 5
|
15天前
|
Kubernetes Go Docker
掌握微服务架构:从Go到容器化的旅程
摘要,通常简短概述文章内容,要求精炼。在本文中,我们将打破常规,采用一种故事化叙述的摘要,旨在激发读者的好奇心和探究欲: “从宁静的海滨小城出发,我们踏上了一场技术探险之旅,探索微服务架构的奥秘。我们将学习如何用Go编写微服务,以及如何通过Docker和Kubernetes将它们打包进小巧的容器中。在这场旅程中,我们将遇到挑战、收获知识,最终实现应用的快速部署与可扩展性。”
|
16天前
|
Cloud Native Java 对象存储
揭秘微服务架构之争:Spring Cloud与Netflix OSS巅峰对决,谁将称霸弹性云原生时代?
近年来,微服务架构成为企业应用的主流设计模式。本文对比了两大热门框架Spring Cloud和Netflix OSS,探讨其在构建弹性微服务方面的表现。Spring Cloud依托Spring Boot,提供全面的微服务解决方案,包括服务注册、配置管理和负载均衡等。Netflix OSS则由一系列可独立或组合使用的组件构成,如Eureka、Hystrix等。两者相比,Spring Cloud更易集成且功能完善,而Netflix OSS则需自行整合组件,但灵活性更高。实际上,两者也可结合使用以发挥各自优势。通过对两者的对比分析,希望为企业在微服务架构选型上提供参考。
37 0
|
1月前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
97 3