基於NIO的消息路由的實現(七)客戶端的一些實現,維持鏈路,斷線重連

1、客戶端代碼存在的必要性以及我認爲須要解決的問題java

就NIO通信自己而言徹底不必分開,其實客戶端代碼和服務端代碼能夠放到一塊兒。可是在業務上是分開的。我在作nio的時候思考了許多我本身認爲應該解決的問題;主要的以下:線程

一、鏈路維護(心跳);code

按期的向服務端發送維持鏈路報文,得到服務端的響應,以證實其仍然在存活狀態;同時服務端會記錄客戶端每次維持鏈路的時間,用於服務端對通道的超時 判斷;對象

二、斷線重連:get

一種狀況是正常斷線,目前我利用對channel的read返回來進行判斷;
it

另外一種是非正常短線,我利用維持鏈路的心跳回應來進行判斷,也就是說,當連續發送固定次數的維持鏈路指令,沒有收到服務端的迴應的時候,主動斷線,啓動重連;io

2、具體實現:class

  一、鏈路維護代碼:channel

  •     定時發送維持鏈路指令;
    nio

  •     判斷維持鏈路指令緩衝區(此緩衝區在每次發送維持鏈路指令的時候會將指令記錄到緩衝區,每次收到鏈路維護迴應報文的時候,會將其所對應的指令清除,若是連續屢次收不到迴應,那麼緩衝區的大小就會達到設置的閾值)的大小,若是達到預設值,就設置客戶端鏈接狀態爲false;重連線程會依據這個標記作是否重連的判斷。

public class KeepChannelThread extends Thread {

    private static Logger logger = LogManager.getLogger(KeepChannelThread.class.getName());
    private int reconnectTag = 0;

    public void run(){
        while(true){

            //構建鏈路維護指令對象
            ClientKeepOrder keepOrder = (ClientKeepOrder)Client.getOrderInstance(ClientKeepOrder.HEADER);
            keepOrder.initClientKeepOrder();
            if (StringUtils.isBlank(keepOrder.getToken())){
                logger.info("未收到服務端分配的身份標識,暫不發送鏈路維護報文!");
                reconnectTag++;
                if (reconnectTag>Client.getKeepTimeoutCount()){
                    Client.clearToken4Disconnect();
                }
            }else {
                reconnectTag = 0;
                try {
                    //觸發重連機制
                    if (Client.KEEP_ORDER_MAP.size()>=Client.getKeepTimeoutCount()){
                        Client.clearToken4Disconnect();
                        logger.info("維持鏈路發現服務端未響應數量達到閾值,進行重連操做!");
                        continue;
                    }
                    //發送鏈路維持報文
                    Client.write2Channel(keepOrder);
                    //保存鏈路維持報文到緩衝區,等待服務端迴應清除。
                    ClientKeepOrder keepOrderValue = new ClientKeepOrder();
                    keepOrderValue = keepOrder;
                    Client.KEEP_ORDER_MAP.put(keepOrder.getRid(), keepOrderValue);
                } catch (IOException e) {
                    e.printStackTrace();
                    continue;
                }
            }
            try {
                Thread.sleep(Client.getKeepAliveCycle()*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
相關文章
相關標籤/搜索