写点什么

netty 系列之: 选 byte 还是选 message? 这是一个问题

作者:程序那些事
  • 2022 年 1 月 04 日
  • 本文字数:2260 字

    阅读完需:约 7 分钟

netty系列之:选byte还是选message?这是一个问题

简介

UDT 给了你两种选择,byte stream 或者 message,到底选哪一种呢?经验告诉我们,只有小学生才做选择题,而我们应该全都要!

类型的定义

UDT 的两种类型是怎么定义的呢?


翻看 com.barchart.udt 包,可以发现这两种类型定义在 TypeUDT 枚举类中。


  STREAM(1),  DATAGRAM(2), 
复制代码


一个叫做 STREAM,它的 code 是 1。一个叫做 DATAGRAM,他的 code 是 2.


根据两个不同的类型我们可以创建不同的 selectorProvider 和 channelFactory。而这两个正是构建 netty 服务所需要的。


在 NioUdtProvider 这个工具类中,netty 为我们提供了 TypeUDT 和 KindUDT 的六种组合 ChannelFactory,他们分别是:


用于 Stream 的:BYTE_ACCEPTOR,BYTE_CONNECTOR,BYTE_RENDEZVOUS。


和用于 Message 的:MESSAGE_ACCEPTOR,MESSAGE_CONNECTOR 和 MESSAGE_RENDEZVOUS。


同样的,还有两个对应的 SelectorProvider,分别是:


BYTE_PROVIDER 和 MESSAGE_PROVIDER.
复制代码

搭建 UDT stream 服务器

如果要搭建 UDT stream 服务器,首先需要使用 NioUdtProvider.BYTE_PROVIDER 来创建 NioEventLoopGroup:


        final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER);        final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER);
复制代码


这里,我们创建两个 eventLoop,分别是 acceptLoop 和 connectLoop。


接下来就是在 ServerBootstrap 中绑定上面的两个 group,并且指定 channelFactory。这里我们需要 NioUdtProvider.BYTE_ACCEPTOR:


final ServerBootstrap boot = new ServerBootstrap();            boot.group(acceptGroup, connectGroup)                    .channelFactory(NioUdtProvider.BYTE_ACCEPTOR)                    .option(ChannelOption.SO_BACKLOG, 10)                    .handler(new LoggingHandler(LogLevel.INFO))                    .childHandler(new ChannelInitializer<UdtChannel>() {                        @Override                        public void initChannel(final UdtChannel ch) {                            ch.pipeline().addLast(                                    new LoggingHandler(LogLevel.INFO),                                    new UDTByteEchoServerHandler());                        }                    });
复制代码


就这么简单。

搭建 UDT message 服务器

搭建 UDT message 服务器的步骤和 stream 很类似,不同的是需要使用 NioUdtProvider.MESSAGE_PROVIDER 作为 selectorProvider:


        final NioEventLoopGroup acceptGroup =                new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.MESSAGE_PROVIDER);        final NioEventLoopGroup connectGroup =                new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
复制代码


然后在绑定 ServerBootstrap 的时候使用 NioUdtProvider.MESSAGE_ACCEPTOR 作为 channelFactory:


final ServerBootstrap boot = new ServerBootstrap();            boot.group(acceptGroup, connectGroup)                    .channelFactory(NioUdtProvider.MESSAGE_ACCEPTOR)                    .option(ChannelOption.SO_BACKLOG, 10)                    .handler(new LoggingHandler(LogLevel.INFO))                    .childHandler(new ChannelInitializer<UdtChannel>() {                        @Override                        public void initChannel(final UdtChannel ch)                                throws Exception {                            ch.pipeline().addLast(                                    new LoggingHandler(LogLevel.INFO),                                    new UDTMsgEchoServerHandler());                        }                    });
复制代码


同样很简单。

Stream 和 Message 的 handler

不同的 UDT 类型,需要使用不同的 handler。


对于 Stream 来说,它的底层是 byte,所以我们的消息处理也是以 byte 的形式进行的,我们以下面的方式来构建 message:


private final ByteBuf message;message = Unpooled.buffer(UDTByteEchoClient.SIZE);        message.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));
复制代码


然后使用 ctx.writeAndFlush(message)将其写入到 channel 中。


对于 message 来说,它实际上格式对 ByteBuf 的封装。netty 中有个对应的类叫做 UdtMessage:


public final class UdtMessage extends DefaultByteBufHolder
复制代码


UdtMessage 是一个 ByteBufHolder,所以它实际上是一个 ByteBuf 的封装。


我们需要将 ByteBuf 封装成 UdtMessage:


private final UdtMessage message;final ByteBuf byteBuf = Unpooled.buffer(UDTMsgEchoClient.SIZE);        byteBuf.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));        message = new UdtMessage(byteBuf);
复制代码


然后将这个 UdtMessage 发送到 channel 中:


ctx.writeAndFlush(message);
复制代码


这样你就学会了在 UDT 协议中使用 stream 和 message 两种数据类型了。

总结

大家可能觉得不同的数据类型原来实现起来这么简单。这全都要归功于 netty 优秀的封装和设计。


感谢 netty!


本文的例子可以参考:learn-netty4


本文已收录于 http://www.flydean.com/40-netty-udt-support-2/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2 小时前
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
netty系列之:选byte还是选message?这是一个问题