儘可能採用無鎖化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.使用前面說的消息分發,封裝爲一個房間操做命令,利用房間線程池來順序處理,便可實現無鎖化。