当前位置: 首页 > 科技观察

为什么王者荣耀不用微服务架构?_0

时间:2023-03-22 01:46:48 科技观察

今天在知乎上看到这个问题:“为什么游戏公司的服务器不愿意微服务?”背景介绍笔者最近采访了一家游戏公司(上市)。我问他,公司对微服务架构有什么规划和考虑吗?他很惊讶,说,我没听说过微服务,你能解释一下吗?我大概说了,易测试、易维护、易升级、服务间松耦合、多语言开发、自动扩展……等等。然后他说游戏服务器不需要微服务,因为需要实时性,而且微服务会影响性能,所以还是模块化开发比较好。我不确定,但微服务不是一种趋势吗?尤其是大公司,游戏服务器的服务应该很容易拆分吧?陈宏基这样回答。比如MOBA游戏/王者荣耀/LOL,你看看王者荣耀的客户端,想象一下。账号系统、符文系统、英雄系统、皮肤系统、好友系统、好友之间的消息等都是常规操作。如果流量够大,当然可以用微服务架构来做。但这不是这款游戏的核心,核心是MOBA:多人在线对战竞技场。有什么特点?10人之间各种游戏事件的高速多方位通讯流媒体/广播/组播/pubsub等多种通讯方式。所以游戏的核心在于小规模群体之间的高速网络交流。对方说的是实时的。如果多了10ms的延迟,玩家就会被骂。微服务为了完美拆解业务,将原来在同一个进程中的模块拆分成不同的服务,这显着增加了额外的网络开销。ServiceMesh就更不用说了,各种Gateway、Proxy、Sidecar简直就是担心延迟太低。微服务基本上只有请求/响应模式。不能做流媒体?微服务通常要求应用程序是无状态的,以便水平扩展。流媒体本身会添加状态。我可以想象,一款英雄联盟游戏为了提高通信性能,可能会使用同一个服务器来负责这10个玩家之间的通信,这样就可以在本地交换数据,从而达到性能最大化。.对客户端或服务端统一网关的要求是必须支持粘性路由。假设客户端连接断开,下一个必须重新连接到与之前相同的服务器。微服务的无状态,水瓶扩展需求本身就是反粘路由,因为粘路由本身就是状态。对于服务器集群来说,有无数个王者荣耀游戏同时进行,每个游戏都可以看作是一个沙盒,每个沙盒都处于不同的状态:推了好几个塔,你被我杀了搞了几次,对面几个超神,都20分钟了吗?这些是长期存在的状态,直到游戏结束,服务器才能清理一局游戏的状态。所以虽然没有必要将这些状态写入到持久化存储中,但它们必然会长期存在于内存中。都是状态。反正有状态就别想用微服务了。除非你说把这些状态都搬到redis上去,那服务器在信息流到一半的时候会去远程请求,一来一去延迟就变大了。反正也不好。(比如假设对方在A你的水晶中,A的每一次操作都是一个事件,流式传输到服务器的沙箱中,沙箱中有一个流处理器,每次收到一个事件你的水晶是A,它会计算你的水晶是否爆炸了。这个计算需要非常快,你不可能把你水晶的生命值数据存储在远端)。这类游戏对网络、内存、CPU优化都有很高的要求。整个游戏过程中,几乎没有RPC调用。确实需要远程数据,应该是prefetch,在游戏开始的时候。加载。微服务不是灵丹妙药,只是为了方便拆解原有的CRUD应用。一是没有触及高级交互方式,二是没有触及分布式系统真正的难点:状态,其实并没有大家想象的那么好用。之所以感觉微服务改变了互联网,是因为90%的互联网应用都只是简单的小规模增删改查。如果对方没有听说过微服务也没关系,因为它本身并不是一个高深的概念。相反,对方听了你就知道微服务不适合做游戏,说明对方理解能力强,对游戏系统设计理解足够深。Brice回答说他玩过棋牌游戏(最简单的一种游戏),他可以尝试说几点:微服务本身就是为了处理业务逻辑的复杂性,需要一种新的接口组织方式。游戏本身的逻辑其实并没有那么复杂。比如大厅,有一些基本的功能,比如修改账号,登录。游戏本身就是游戏本身的逻辑。游戏逻辑服务器(如棋牌类游戏)本身有网络响应性能要求(玩家对每次操作的反馈时间的敏感度远高于业务系统),所以游戏服务器是有状态的,状态存在于内存中,偶尔接受Redis、MySQL等是绝对不能接受的。关系行数据库只是用来定时异步持久化数据,只有游戏服务器才可以在Redis中持久化数据。游戏服务器一般需要主动推送,第一代微服务网关无法满足需求。TCP没有网关,可能会用到SpringCloudGateway的Websocket(但是从防攻击的角度来说,端游用TCP肯定比Websocket好是合理的)。Ribbon、Feign等不适合服务间通信RPC,因为它们都是基于http的。使用http时存在消息乱序的问题。比如一个玩家出牌两次,在http中可能会出现顺序不一致的情况。游戏服务器集群一般使用长连接互连。也许你需要使用Dubbo?(据说是长连接)游戏逻辑服务器(比如游戏服务器),一般不能用SpringMVC来做,因为线程模型完全不同。多线程模型游戏性能差,非常复杂。一般用单个进程/线程驱动固定数量的房间(这就是为什么服务器必须有状态,不能直接读写MySQL)。一般直接是Netty。自动扩容在游戏端称为开服,长期以来一直有固定的流程、工具和限流方式。游戏中的很多操作都没有服务降级熔断器,如果失败会直接报错给用户。大堂服务器登录、注册等确实可以作为微服务使用,但实际上它们并不是微服务,只是几个接口自动横向扩展的方案。发现注册服务用处不大,开服是板上钉钉的事,还有一系列操作手段配合,关服千万不能随便关。游戏处理的流量真的不多。10000个在线棋牌游戏已经可以赚很多钱,10W是一个特别强大的产品。一些独立的服务器比如充值需要做微服务吗?只能说这种服务端需要微服务来处理,项目组才能梦寐以求。虽然上面说了很多点,其实你可以考虑用SpringCloud来改造一下,因为游戏集群也有注册中心,需要服务发现和启动顺序,但是SpringCloud并不是为游戏设计的。比如至少要全面支持WebFlux(我没仔细研究过),如果需要单线程长连接,最好支持ProtobufRPC框架(集成服务发现相关功能和接口),网关支持TCP或者至少封装或者暴露一些Netty的Decoder编码器(或者允许注入)等等。