netty系列之:真正的平等–UDT中的Rendezvous

flydean發表於2022-02-11

簡介

在我們之前提到的所有netty知識中,netty好像都被分為客戶端和伺服器端兩部分。伺服器端監聽連線,並對連線中的訊息進行處理。而客戶端則向伺服器端建立請求連線,從而可以傳送訊息。

但是這一切都要在UDT協議中被終結,因為UDT提供了Rendezvous,一種平等的連線型別,節點之間是對等關係。

從來都沒有救世主,也沒有神仙和皇帝,只有同為節點的好兄弟。

建立支援Rendezvous的伺服器

因為是對等的關係,所以這裡不需要使用到ServerBootstrap,使用普通的Bootstrap就夠了。

group還是要的,這裡使用NioEventLoopGroup,NioEventLoopGroup需要提供了SelectorProvider。UDT提供了兩種provider,分別是NioUdtProvider.BYTE_PROVIDER 和 NioUdtProvider.MESSAGE_PROVIDER,分別表示stream和message兩種格式:

final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
                connectFactory, NioUdtProvider.BYTE_PROVIDER);

final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
                connectFactory, NioUdtProvider.MESSAGE_PROVIDER);

接下來就是建立Bootstrap,並繫結group和設定channelFactory.

當然,這裡的channelFactory也有兩種,分別是NiNioUdtProvider.BYTE_RENDEZVOUS和NioUdtProvider.BYTE_RENDEZVOUS。

那麼可以有下面兩種建立的方法,第一種是byte stream的:

 final Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(connectGroup)
                    .channelFactory(NioUdtProvider.BYTE_RENDEZVOUS)
                    .handler(new ChannelInitializer<UdtChannel>() {
                        @Override
                        protected void initChannel(UdtChannel ch) throws Exception {
                            ch.pipeline().addLast(
                                    new LoggingHandler(LogLevel.INFO),
                                    new UDTByteHandler(messageSize));

第二種是message的:

final Bootstrap boot = new Bootstrap();
            boot.group(connectGroup)
                    .channelFactory(NioUdtProvider.MESSAGE_RENDEZVOUS)
                    .handler(new ChannelInitializer<UdtChannel>() {
                        @Override
                        public void initChannel(final UdtChannel ch)
                                throws Exception {
                            ch.pipeline().addLast(
                                    new LoggingHandler(LogLevel.INFO),
                                    new UDTMsgHandler(messageSize));
                        }
                    });

至此,兩個支援不同UDT型別的Rendezvous伺服器就建立起來了。

接下來就是對訊息的處理了。

處理不同的訊息

有了支援byte和message兩種格式的伺服器,接下來就是如何處理對應的訊息了。

對於byte格式的UDT,channel中傳輸的訊息就是ByteBuf,我們只需要構建ByteBuf的訊息,然後在channel中傳輸即可:

private final ByteBuf message
message = Unpooled.buffer(messageSize);
message.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));
ctx.writeAndFlush(message);

對應message格式的UDT,netty提供了一個專門的類UdtMessage對其進行封裝,UdtMessage繼承值DefaultByteBufHolder,他就是對ByteBuf的封裝。

我們可以這樣建立一個UdtMessage併傳送它:

private final UdtMessage message;
final ByteBuf byteBuf = Unpooled.buffer(messageSize);
byteBuf.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));
message = new UdtMessage(byteBuf);

ctx.writeAndFlush(message);

節點之間的互動

上面我們分別建立了兩個節點,這兩個節點是對等關係,那麼怎麼將這兩個節點聯絡起來呢?

我們呼叫Bootstrap的connect方法如下:

final ChannelFuture f = boot.connect(peer, self).sync();
            f.channel().closeFuture().sync();

這裡的connect傳入兩個SocketAddress引數,第一個引數是remoteAddress,第二個參數列示的是localAddress.

當然,connect還有一種常用的用法就是連線到遠端的伺服器:

public ChannelFuture connect(String inetHost, int inetPort)

這也是我們最常見的那種用法。

總結

以上就是UDT中的Rendezvous的使用。

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

本文已收錄於 http://www.flydean.com/41-netty-udt-byte-message/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章