netty中的发送有序与channel使用

简单写一个示例代码:

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg.toString());
        t = msg;
        ctx.write(msg);
       ctx.fireChannelRead(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // TODO Auto-generated method stub
        ctx.flush();
        super.channelReadComplete(ctx);
    }

这个代码在ctx.fireChannelRead(msg);的时候,最终会调用到tail的inboundhandle。tail inboundhandle是netty默认的最后一个处理

msg的handle。将msg进行realse。那么当 ctx.flush();的时候,msg已经被释放掉,再读取msg,就会报错。

所以如果直接写 ctx.write(msg);复用msg的时候,坚决不能释放msg的引用。那么msg的引用什么时间会被释放呢?

当flush调用成功后,真正写入channel以后,DefaultChannelPipeline$HeadContext,最终会调用ChannelOutboundBuffer的

remove方法,将已经写入的内容从待写的链表中删除。

    public boolean remove() {
        Entry e = flushedEntry;
        if (e == null) {
            clearNioBuffers();
            return false;
        }
        Object msg = e.msg;

        ChannelPromise promise = e.promise;
        int size = e.pendingSize;

        removeEntry(e);

        if (!e.cancelled) {
            // only release message, notify and decrement if it was not canceled before.
            ReferenceCountUtil.safeRelease(msg);
            safeSuccess(promise);
            decrementPendingOutboundBytes(size, false, true);
        }

        // recycle the entry
        e.recycle();

        return true;
    }

在ReferenceCountUtil.safeRelease(msg);会删除掉msg的引用。释放msg。

总之,在tail的inboundhandle会free掉msg。而head的outboundhandle会在写入channel后,free掉msg。

如果需要在inbound中回写msg。可以参见《netty 实战》的2.3.1的写法。

注意如下写法也会报错:

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(msg.toString());
        t = msg;
        ctx.writeAndFlush(msg);
       ctx.fireChannelRead(msg);
    }

这是因为ctx.writeAndFlush(msg)执行成功后(真正写入到channel中,因为writeandflush可能尝试16次依然无法写入成功

会放入到队列中下次继续写),msg会被释放。当ctx.firechannelRead到tail handle时,会因为msg的引用已经为0,而报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用 Netty 的集群,您可以使用 `ChannelGroup.find()` 方法来通过 channel ID 获取 channel 对象。首先,您需要创建一个 `ChannelGroup` 对象,然后将所有 channel 添加到该对象。例如: ``` ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); // 添加 channelchannelGroup channelGroup.add(channel1); channelGroup.add(channel2); ... // 通过 channel ID 获取 channel Channel channel = channelGroup.find(channelId); ``` 如果找不到与给定 ID 匹配的 channel,则返回 `null`。 注意:这种方法的性能可能较低,因为它需要遍历整个 channelGroup 以查找与给定 ID 匹配的 channel。如果您需要快速查找 channel,可以考虑使用其他数据结构(例如,哈希表)来存储 channel。 ### 回答2: NettyChannelId是用来唯一标识一个Channel对象的。每个Channel对象都会在创建时自动创建一个唯一的ChannelId,可以通过Channel的方法`id()`来获取该ChannelChannelId。 在一个集群环境,不同的Netty服务器上可能存在多个Channel对象,通过ChannelId可以准确地找到对应的Channel对象。为了实现这一功能,可以使用NettyChannelGroup类。ChannelGroup是一个用来管理多个Channel对象的容器,可以通过ChannelId来获取对应的Channel对象。 首先,在创建Channel时,可以将Channel对象添加到ChannelGroup,例如: ```java ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); channelGroup.add(channel); ``` 接下来,可以通过ChannelId来查找对应的Channel对象,例如: ```java ChannelId channelId = channel.id(); Channel channel = channelGroup.find(channelId); ``` 通过以上的代码,可以通过ChannelId在集群查找到对应的Channel对象。 需要注意的是,当Channel对象关闭时,应该将其从ChannelGroup移除,避免无用的Channel对象占用资源: ```java channelGroup.remove(channel); ``` 通过上述方法,可以在集群环境通过ChannelId来获取和管理Channel对象。 ### 回答3: 在Netty,可以通过ChannelId来获取对应的Channel对象。ChannelId是一个在Channel被创建时自动生成的唯一标识符,可以用来检索和管理Channel对象。 要通过ChannelId获取Channel对象,可以使用ChannelGroup或ChannelGroupMap来实现。ChannelGroup是一个用于管理多个Channel对象的集合,而ChannelGroupMap是一个能够将ChannelId与Channel对象进行映射的Map。 首先,我们可以创建一个ChannelGroup对象,用于管理所有连接到集群的Channel。通过调用ChannelGroup的add方法,我们可以将每个新加入集群的Channel对象添加到ChannelGroup,以便进行管理。 接着,当需要根据ChannelId获取对应的Channel对象时,可以调用ChannelGroup的find方法,并传入要查找的ChannelId作为参数。这样,ChannelGroup会返回一个对应的Channel对象,可以通过该对象进行后续操作。 此外,在Netty还可以使用ChannelGroupMap来实现更灵活的标识符到Channel对象的映射。ChannelGroupMap是一个将ChannelId与Channel对象一一映射的Map数据结构。通过在ChannelGroupMap保存ChannelId和对应的Channel对象的关系,可以直接通过ChannelId获取对应的Channel对象,而无需再遍历整个ChannelGroup。 总结起来,通过ChannelId可以在Netty的集群获取对应的Channel对象。通过ChannelGroup或ChannelGroupMap等数据结构,可以方便地管理和操作各个Channel对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值