【服务器框架】棋牌游戏服务器架构设计

1、前言

棋牌类游戏服务器构架设计分析html

2、原文

原文地址:http://bbs.gameres.com/thread_703363_1_1.html
原文做者:小篱
原文出处:GameRes游资网mysql

3、正文

棋牌游戏服务器架构设计

这里写图片描述

一,棋牌类服务器的特色

1,棋牌类不分区不分服

  通常来讲,棋牌游戏都是不分区不分服的。因此棋牌类服务器要知足随着用户量的增长而扩展的须要。nginx

2,房间模式

  即在同一局游戏中就是在同一个房间中,同一个房间中的人能够接收到其余人的消息。程序员

3,每一个房间的操做必须是顺序性

  这个特性相似与通常游戏的回合制,每一个玩家的操做都是有顺序性的。web

二,须要解决的技术点

1,数据共享

  由于棋牌类游戏不分区不分服,咱们在设计服务器的时候,是按世界服的思想去设计,即服务器是一个n多台物理机的集群。当用户登录服务器,建立房间时,可能根据负载均衡算法,它能够在任何一台服务器上面。因此,无论用户登录到哪一台服务器上面了,均可以得到本身的数据。咱们可使用redis来作数据共享。redis

2,如何进入房间

  在同一局游戏中,咱们要求全部人都在同一个房间中,咱们能够规定在同一个房间中的用户,必须登录到同一台物理服务器上面。在建立房间完成以后,其余人根据房间号查找房间的时候,能够根据房间号,获取这个房间所在的服务器ip和端口,判断一个当前用户登录的服务器ip与房间所在的服务器ip是否相同,若是相同,就不作切换,若是不同,客户端就使用ip和端口,链接到房间所在的服务器上面。算法

3,保证房间操做的顺序性

  建立房间成功以后,接下来的操做都要保证它的顺序性,因此房间须要有一个它本身的消息个队列。咱们能够把每一个房间到达服务器的消息封装为一个任务,把这个任务放到消息队列中,而后有一个任务执行者去按顺序执行这些任务。sql

三,系统架构

1,功能设计

a,登录

  通常都是须要接第三方登录,登录这一块是http操做,咱们统一提供一个web服务,用来作登录验证。由于在登录时,调用第三方的http服务,这个过程可能很慢,若是放在逻辑服务器的话,可能会卡业务逻辑任务。由于可能不一样的玩家业务请求可能同在一个线程中,若是有任务卡了,那么这个任务之后新来的请求请会卡住,致使消息延迟。数据库

b,获取游戏公告

也放在web服务中。公告通常是游戏登录的时候向服务器获取一次。把它放在web服务器中,与业务逻辑分离的好处是,当业务逻辑服务器维护或更新的时候,不影响用户的登录,和获取公告,这样用户体验会好一些。缓存

c,建立用户惟一的id

由于棋牌类游戏服务器是世界服,无分区,因此用户的id必须是全局惟一的。能够利用redis的incr方法,原子的递增,若是不想被别人根据userid的递增推算出有多少注册用户,递增的梯度能够随机,好比每次递增的值从1到1024中随机一个。

d,建立房间

当房间主建立房间时,房间的id须要在任何台服务器上能够查询到,因此建立房间成功后,房间id要存储在共享内存redis中,每一个房间id对应一个房间所在的ip地址或服务器id.这样,当有用户要进入房间,在查询房间id时,可能判断这个房间是否和本身登录的游戏服务器相同。

e,查找加入房间

  根据房间id查询房间,查找到房间后,获取房间所在的ip地址或服务器id,若是发现和本身所登录的服务器同样,直接能够加入房间。若是不同,把这个房间所在的ip和端口返回给客户端,让客户端从新与房间所在的服务器创建链接,使用登录时的token验证用户。

f,游戏脚本调用

  在验证游戏是否合法时,客户端与服务器都要验证,验证的算法是同样的,因此可使用脚原本写,写一份脚本,在服务器与客户端中同时使用。可使用lua。同一个算法使用同一个脚本 ,这样在开发新的同类型棋牌游戏时,只须要替换一下这个脚本就好了,不用再重复开发。

2,后台管理系统

  这个通常是根据运营需求开发的,每一个公司不同。不过有一点,后台管理系统可能要和游戏服务器通讯,这种通讯方式最好是采用redis的订阅/发布机制。这样能够把某个消息事件同时发送到全部的业务服务器上面。根据用户所在的服务器进行处理。

3,玩家同屏

  玩家同屏是棋牌游戏中的一个重点,对于作过那些大型的arpg,或mmo游戏的程序员来讲,这并非什么难事。由于同屏就是服务器对客户端的消息进行转发。一个房间四我的,一我的出的牌或操做能被其余三我的同时看到。

由于棋牌游戏的同步数据量比较小。通常常见的同步方式有两种:

  • 客户端主动拉取

      客户端定时主动向服务器请求一个用户的消息队列,当一个玩家有操做须要同步到其余玩家时,在服务器端先把这个消息放到这个用户的消息队列中。等待客户端的拉取操做。这种方式的好处是,不须要考虑网络闪断或网络很差的状况,信息都是同步获取的。缺点是,定时拉取的时间间隔很短,可能不到一秒就会拉取一次。

  • 客户端主动推送

      当一个用户出牌的消息须要同步给其余玩家时,服务器会得到这个玩家与服务器创建的socket链接,而后服务器使用socket 主动向客户端发送消息。

      这种方式要考虑网络闪断,消息丢失的问题。由于服务器推送的消息,客户端有可能会收不到。因此客户端须要根据心跳来判断网络是否有断开过,若是有断开,须要从新从服务器拉取整个房间状态的消息。或者根据服务器发送的消息号,若是客户端发现接收到的服务器消息号有跳号的,好比应该接收10,却收到了12,说明中间有消息丢失,须要从新拉取整个房间的状态信息。

      这种方式的缺点是,开发复杂,须要考虑一些网络问题。优势是,只有在有消息的时候才会推送,没有的话不推送,不占用带宽等系统资源,能够增长用户同时在线量,也就是增长了服务器的承载量。

4,数据同步和持久化

1,因为棋牌类的游戏数据少,计算量也小,因此彻底能够不使用内存缓存,而直接使用redis共享内存,用户的全部数据都缓存在redis中。更新也同步更新到redis中,这样无论一个用户登录哪一台业务服务器,都能得到本身的最新数据。

2,更新数据库,因为数据第一缓存是redis,因此活跃的用户数据都是能够从redis中直接得到的,而不用查询数据库,因此数据库的更新能够采起异步更新,而不会产会数据的延迟。须要注意的一点是,数据的异步更新必须保证是有顺序的。那么这就会产生一个问题,怎么保证用户的更新不会乱呢?

3,如何保证更新的顺序性

  由于咱们的业务服务器是多个的,用户可能链接其中的任何一个,若是说登录的是服务器A,加入的房间在服务器B上,那么链接就会切换。为了保证数据更新的顺序,咱们能够作一个数据库持久化服务,把须要更新数据库的任务实时发送到这台服务器上,由数据库持久化服务执行对数据库的更新。这样无论用户链接的哪台业务服务器,它的更新都是有顺序保证的。

5,一种快速简单的方法

  因为棋牌类的业务少,数据更新少,因此查询能够有redis缓存,减小数据库查询的压力,而更新实行实时更新到数据库,前期不须要开发数据库持久化服务。等用户积累到必定程序以后,发现更新数据库比较慢的时候,再单独作一个数据库持久化服务。

四,服务器架构

这里写图片描述
  1,登录时,客户端首先向登录的web服务器请求登录信息,登录成功以后,返回登录的token,为了适应大规模的web请求和登录服务的稳定,可使用nginx作负载均衡。

  2,登录成功以后,请求负载均衡服务器,获取一台链接的业务服务器。这个负载均衡服务器能够和登录web在一个进程中,也能够独立出来。

  3,拿到登录成功的token和须要链接的业务服务器的ip和端口以后,再去链接业务服务器。链接成功以后,要使用token到登录服务器去验证,这个用户是否登录了。

  4,同一个房间的用户要链接到同一台物理服务器上面。在上面已经说过了。

  5,redis用来作共享缓存。

  6,mysql作持久化存储。

  7,数据库持久化服务器,统一作数据入库操做。

五,关于网关的问题

  1,网关的做用

  a,转发消息包

  b,业务的负载均衡,好比A业务由服务器a处理,B业务由服务器b处理,由网关进行转发。

  c,维护与客户端的链接

  d,带宽的整合,通常的云服务都是按购买的服务器计算带宽的。经过一台服务器转发消息,能够只购买一个大带宽就能够了。以节约成本。

  2,棋牌类游戏须要网关吗?

  我认为不太须要,由于棋牌类游戏业务比较单一,作的最多的就是消息同屏转发。最可能是再有一些任务或活动,这些由一台服务器直接处理彻底能够搞定。并且开发网关也是一个复杂的工做,不必在这个上面花太多的时间。