0920-TCP断线重连 reconnect

问题

最近使用AD域LDAP通信碰到一个TCP底层问题,一个链接第一次点击失败,再点击就正常;

过一段时间又会出现这一情况;

跟踪日志发现:The connection is not established

定位问题:连接是有的,但是没有保活(自行百度)

建立连接后,过了很久连接中断,但是客户端没有收到服务端的信息,认为是有效连接,尝试连接时会报错

解决办法

1 客户端和服务端设置保活

理论上,下一个心跳周期前连接断了,还是会有这个问题

                //TCP保活 超时时间
                options.setUseKeepAlive(true);
                options.setConnectTimeoutMillis(CONNECT_TIMEOUT);
                options.setResponseTimeoutMillis(RESPONSE_TIMEOUT);

                connection = new LDAPConnection(sslSocketFactory,
                        options,
                        adIpAddress,
                        adDef.getAdPort(),
                        adminDN,
                        adDef.getAdAdminPassword());
                connectionPool = new LDAPConnectionPool(connection, adDef.getAdMaxPoolCount());

2 断线重连机制(根本解决)

在发起业务请求前,先发起一个请求检测是否有效,

如果无效会抛出异常,catch异常尝试重连 ,如果超过重试次数抛出异常

//发请求前,随意发起一个状态请求(任何内容,尽可能小),如果抛异常则尝试重连
checkAndReconnect(ldapConnection);
//发起真正的业务请求
modResult = ldapConnection.modify(adUser.getUserDN(), mods);

 

    /**
     * 检查连接并重试
     * @param connection LDAP连接
     */

    private static void checkAndReconnect(LDAPConnection connection){
        Preconditions.checkNotNull(connection, LOG_PREFIX+"空连接,请检查网络");
        try {
            connection.getRootDSE();
        } catch (LDAPException e) {
            int i;
            for (i = 0; i < RECONNECT_TIMES; i++) {
                try {
                    connection.reconnect();
                    log.info(LOG_PREFIX+"重连..{} 成功",i+1);
                    return;
                } catch (LDAPException e1) {
                    log.info(LOG_PREFIX+"重连..{} 失败{}",i+1,e.getResultString());
                }
            }
            throw Exceptions.newBusinessException(LOG_PREFIX+"重连"+i+"次失败,网络可能已经断开");
        }
    }

 

测试

模拟网络断开

Windows防火墙模拟网络断开

开发机是windows,使用防火墙屏蔽端口,出战规则屏蔽端口,启动规则,模拟连接突然断开

Linux防火墙模拟网络断开

//打开防火墙配置文件
vim /etc/sysconfig/iptables
//iptables添加屏蔽规则  
-A OUTPUT -p tcp --dport 23000 -j DROP
//重启iptables使规则生效
systemctl restart iptables
//telnet模拟防火墙是否生效
telnet 192.168.1.17 23000

 测试成功(中间开启屏蔽规则,放开后连接成功)

心得体会

  • 不能通过状态检测来确认连接是否正常

比如不能以isConnected()的结果作为是否连接的标准,它只是一个结果

连接本质上是一个对象,所谓的状态只是一个成员变量,可能网络断了,但状态还是之前正常连接的状态

  • 通过尝试连接是否抛异常来判断连接状态及尝试重连

所以简单来说,就是要看方法是否抛异常,如果抛异常,那么它底层的确是去连接了,所以才知道状态

  • 通过防火墙模拟网络连接
  • debug模式可以在需要的时候才打断点,不需要提前打断点

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值