基于NIO的消息路由的实现(七)客户端的一些实现,维持链路,断线重连

China☆狼群 提交于 2019-12-07 15:46:38

一、客户端代码存在的必要性以及我认为需要解决的问题

就NIO通讯本身而言完全没必要分开,其实客户端代码和服务端代码可以放到一起。但是在业务上是分开的。我在做nio的时候思考了许多我自己认为应该解决的问题;主要的如下:

1、链路维护(心跳);

定期的向服务端发送维持链路报文,获得服务端的响应,以证明其仍然在存活状态;同时服务端会记录客户端每次维持链路的时间,用于服务端对通道的超时 判断;

2、断线重连:

一种情况是正常断线,目前我利用对channel的read返回来进行判断;

另一种是非正常短线,我利用维持链路的心跳回应来进行判断,也就是说,当连续发送固定次数的维持链路指令,没有收到服务端的回应的时候,主动断线,启动重连;

二、具体实现:

  1、链路维护代码:

  •     定时发送维持链路指令;

  •     判断维持链路指令缓冲区(此缓冲区在每次发送维持链路指令的时候会将指令记录到缓冲区,每次收到链路维护回应报文的时候,会将其所对应的指令清除,如果连续多次收不到回应,那么缓冲区的大小就会达到设置的阈值)的大小,如果达到预设值,就设置客户端连接状态为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();
            }
        }
    }
}


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!