当前位置: 首页 > Linux

使用AKKA搭建分布式游戏服务器

时间:2023-04-06 23:04:07 Linux

长期以来,分布式服务器一直是服务器开发中比较先进的概念。其实了解分布式的人并不多,所以今天打算分享一下如何实现java的分布式游戏服务器。对于erlang、golang等函数式语言,实现分发不是很方便,但是如果使用akka组件,问题就迎刃而解了。首先,大部分游戏服务器都需要解决并发问题。传统的命令式编程并不能很好的解决这个问题,所以大部分java面试肯定会问多线程和并发的问题,而函数式语言,自然就解决了这个问题。如果你学过erlang和golang,网上有相关资料。你搜一下github,golang的项目很多,但是用golang并不代表你用的是分布式。先了解一个概念,erlang实现的actor模型是否可以用java实现。答案是肯定的,scala中有actor的实现,但是如果你用akka,就用akka的actor,不用scala的actor。是否仅通过演员来实现分配?不是分布式的概念,是指节点之间的通信,所以简单的节点通信应该是远程的,那么用java和golang实现远程方便吗?remote需要知道本节点(ip-actorname)----》othernode(ip-actorname),那么在实际实现中,需要在代码中为每个节点的ip和actor注册几个点,并找到了。是的,目前java可以通过rmi,dubbo,akka等方式实现duboo,比较麻烦,需要定义很多接口,每个节点都需要注册。所以在游戏服务器中,这样可以吗?不行,因为当你扩展你的节点时,你会发现你无法分辨你要通信的玩家当前登录的是哪个节点,所以这时候你需要解决的就是路由问题。就是为了解决这个问题,游戏服务器集群推荐使用golang,或者java(akka)实现一套集群,自动路由,水平扩展的分布式服务器golang集群,代理访问和使用shardRegion访问的区别在于,这两种访问方式太重要了。此外,这是一个单例代理privatefunstartUniverseCwarManager(){valsettings=ClusterSingletonManagerSettings.create(actorSystem).withRole(ClusterRole.universe_cwar.name)actorSystem.actorOf(ClusterSingletonManager.props(UniverseCwarManager.props(),Handoff,settings),UNIVERSE_CWAR_MANAGER)}可以通过以下方式访问上面创建的集群单例actorOf(ClusterSingletonProxy.props(universeRole.proxyPath,proxySettings))universeProxies[universeRole]=actorRef}worldActor创建另一个访问对象/**actors分布在universe_cwar节点上*/privatefunstartUniverseCwarShardRegion(){valsettings=ClusterShardingSettings.创建(actorSystem).withRole(ClusterRole.universe_cwar.name)valregion=ClusterSharding.get(actorSystem).start(GameWorldShard.universe_cwar.name,UniverseCwarWorld.props(),设置,UCWorldMessageExtractor(),ShardCoordinator.LeastShardAllocationStrategy(5,1),Handoff)logger.info("SharedRegion$regionstarted.")ClusterClientReceptionist.get(actorSystem).registerService(region)}这样创建的Clustershards,通过下面的proxyisaccessed/**检索负责指定实体类型的[[ShardRegion]]actor的actor引用。实体类型必须先使用[[#start]]或[[#startProxy]]方法注册,然后才能在此处使用。发送给实体的消息始终通过ShardRegion发送。*/只要protectedfunstartUniverseCwarShardProxy(){ClusterSharding.get(actorSystem).startProxy(GameWorldShard.universe_cwar.name,Optional.of(ClusterRole.universe_cwar.name),UCWorldMessageExtractor()).let{logger.info("UniverseCwarshardproxy$itstarted.")}},可以得到ClusterSharding.get(context.system()).let{ucWorldShardProxy=it.shardRegion(GameWorldShard.universe_cwar.name)}