尽可能采用无锁化Netty通讯处理棋牌房间逻辑java
一,棋牌类服务器的特色redis
1,棋牌类不分区不分服算法
通常来讲,棋牌游戏都是不分区不分服的。因此棋牌类服务器要知足随着用户量的增长而扩展的须要,因此须要设计Gate网关来处理链接到哪一个逻辑服务器。安全
2,房间模式服务器
即在同一局游戏中就是在同一个房间中,同一个房间中的人能够接收到其余人的消息。多线程
3,每一个房间的操做必须是顺序性负载均衡
这个特性相似与通常游戏的回合制,每一个玩家的操做都是有顺序性的。ide
二,须要解决的技术点线程
1,数据共享设计
由于棋牌类游戏不分区不分服,咱们在设计服务器的时候,是按世界服的思想去设计,即服务器是一个n多台物理机的集群。当用户登录服务器,建立房间时,可能根据负载均衡算法,它能够在任何一台服务器上面。因此,无论用户登录到哪一台服务器上面了,均可以得到本身的数据。咱们可使用redis来作数据共享。
2,如何进入房间
在同一局游戏中,咱们要求全部人都在同一个房间中,咱们能够规定在同一个房间中的用户,必须登录到同一台物理服务器上面。在建立房间完成以后,其余人根据房间号查找房间的时候,能够根据房间号,获取这个房间所在的服务器ip和端口,判断一个当前用户登录的服务器ip与房间所在的服务器ip是否相同,若是相同,就不作切换,若是不同,客户端就使用ip和端口,链接到房间所在的服务器上面。
3,保证房间操做的顺序性
建立房间成功以后,接下来的操做都要保证它的顺序性,因此房间须要有一个它本身的消息个队列。咱们能够把每一个房间到达服务器的消息封装为一个任务,把这个任务放到消息队列中,而后有一个任务执行者去按顺序执行这些任务。
以上三个问题,咱们着重讲的是第三个问题:咱们目前作的是一台逻辑服务器,没有涉及网关。
对于Netty来讲,今后处获得消息以后,能够直接进行解析处理,在这儿我作了一个 private EventExecutor messageExecutor;用一个单线程来处理大厅消息。
对于房间消息,采用三个线程来处理,根据房间号求余三个线程,让不一样的房间消息,使用着相同的线程来处理,避免了锁的处理。
如下是单线程消息分发器,分发知乎
int nthread=3;
int roomid = Integer.parseInt(JsonUtil.GetData(request.GetMessage(), "roomid").toString());
int thread = roomid % nthreads;
// 分三个线程执行
private EventExecutor[] executors = new DefaultEventExecutor[nthreads];
executors[thread].execute(new Runnable() {
@Override
public void run() {
int id = request.GetMessageId();
try {
handleMap.get(id).execute(request); //消息处理器handleMap
} catch (java.lang.NullPointerException ex) {
System.out.println(ex.toString());
}
}
});
还须要考虑另一种状况业务状况是,“若是设置定时器,10分钟内房间无操做,则强制解散房间”。这个时候也涉及到多线程对房间操做处理:
这个时候有两种方式:
1.考虑线程安全
2.使用前面说的消息分发,封装为一个房间操做命令,利用房间线程池来顺序处理,便可实现无锁化。