Netty中重连可能出现 is not a @Sharable handler 报错的处理方法

场景描述

采用netty时进行udp的连接,代码如下,初始连接正常,当网络进行重连时就开始报错:is not a @Sharable handler

    public boolean connect(){
        String host = utils.getPropStr("wincc-ip", "47.93.26.231");
        int port = Integer.valueOf(utils.getPropStr("wincc-port", "13731"));     
        closeClient();
        if(bootstrap==null) {          
            bootstrap = getBootStrap();
        }
        channelFuture = bootstrap.connect(host, port); 
        channelFuture.syncUninterruptibly();    
        if(channelFuture!=null && channelFuture.isSuccess()){
            channel = channelFuture.channel();
            protocol.mChannel = channelFuture.channel();           
            return true;
        }else{            
            return false;
        }
    }

问题分析

分析链接:https://blog.youkuaiyun.com/haoziwlh/article/details/77684938
  1.在写一个netty客户端时,对应的handler没有增加sharable注解,
  2.当执行重连的逻辑时,此时会收到一个莫名其妙的错误java.nio.channels.ClosedChannelException
  3.客户端每次connect都会重新建立一个channel。因为ClientHandler没有使用sharable注解
  4.对于一个非sharable注解的handler,在第一次connect的时候isSharable()方法返回false,但是h.added是返回false的,可以通过
  5.但当第二次被加入时,就出问题了isSharable()方法还是返回false,h.added也是true了,所以会抛出ChannelPipelineException
  6.ChannelInitializer对应的channelRegistered方法捕捉到此异常后,没有执行success = true,导致ctx.close()方法执行
  7.进而在connect的时候,ensureOpen方法将promise设置为CLOSED_CHANNEL_EXCEPTION,返回了,导致连接失败
@Sharable的真实含义

一.当netty尝试往多个channel的pipeline中添加同一个ChannelHandlerAdapter实例时,
  会判断该实例类是否添加了@Sharable,没有则抛出异常
  .. is not a @Sharable handler, so can't be added or removed multiple times

  1.如果你添加的不是单例Handler,你加不加@Sharable没有任何区别
  2.如果你添加的是单例Handler,只要它会被添加到多个channel的pipeline,那就必须加上@Sharable

二.网上有些资料说netty会将注解了@Sharable的Handler单例化,实在误导人。
   1.channelHandler是不是单例跟netty没有任何关系
   2.netty只会在你尝试用单例ChannelHandler时加上第1条说明的限制
   3.这个限制意思很明确,多个channel公用单例ChannelHandler,那它就必须是线程安全的
   4.@Sharable就是用于告诉netty,我这个Handler是线程安全的,可以被多个channel安全的share
   5.假如你搞了个线程不安全的类,你对它用上了单例,还加个@Sharable,这时候netty拿你也没办法,

处理方法

方法:在ServerChannel类上添加@ChannelHandler.Sharable注解就可以了

@ChannelHandler.Sharable
public class UdpClientHandler extends SimpleChannelInboundHandler<Object> {
、、、
}
//这个注解适用于标注一个channel handler可以被多个channel安全地共享。


1.重新new一个channel 等待客户端的连接
2.对于对应使用的服务器的channelHandler类可以添加注解@ChannelHandler.Sharable
这个注解就是让这个handler可以被多个channel共享
当客户端重连时可以重新连接上服务端并且正常的发送数据。

补充说明

实际方案应该有多种

方案一:对应使用的服务器的channelHandler类可以添加注解@ChannelHandler.Sharable
	 该方案验证可行
方案二:重新new一个channel 等待客户端的连接
     实际使用中出现通道冲突问题,由于时间原因未进一步验证

参考连接:

https://blog.youkuaiyun.com/haoziwlh/article/details/77684938
https://blog.youkuaiyun.com/wb_snail/article/details/106263470
https://blog.youkuaiyun.com/qq_28198181/article/details/82669656

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值