中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

netty的maven怎么配置

發布時間:2022-01-06 15:21:15 來源:億速云 閱讀:274 作者:iii 欄目:大數據

本篇內容主要講解“netty的maven怎么配置”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“netty的maven怎么配置”吧!

    Netty被廣泛使用在各種場景,如Dubbo服務的遠程通信、Hadoop的shuffle過程、游戲領域的client和server通訊等等。Netty可以非常方便的定義各種私有協議棧,是網絡編程的利器。Netty是對NIO的封裝,Netty沒有封裝AIO是因為Linux的AIO也是用epoll來實現的,性能并非有太大提升,且Netty的reactor模型并不適合封裝AIO,故而Netty放棄了對AIO的支持。物聯網的興起,大量設備需要互聯,Netty必然是其中的利器。

    傳統的NIO編程模型中需要用輪詢器selector去輪詢每個通道是否有讀寫事件發生,且ByteBuffer api晦澀難懂,維護起來非常復雜,業務很難解耦,Netty幫我們屏蔽了NIO的細節,且做很多性能優化。下面我們就來看看Netty中的一些細節。

 說明:以下例子netty版本號為4.1.52.Final,maven配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.netty</groupId>
	<artifactId>netty-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>netty-demo</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>io.netty</groupId>
			<artifactId>netty-all</artifactId>
			<version>4.1.52.Final</version>
		</dependency>
	</dependencies>
</project>

一、client端和server端的啟動

    1、server端

    ServerBootstrap里的group方法有兩個入參都是NioEventLoopGroup,是兩個線程池,分別表示接受請求的線程和處理請求的線程,這就是reactor模型的體現,每個客戶端連接進來,server端便有一個channel與之對應,childHandler方法便是給channel綁定一堆處理器,這里綁定了三個入站處理器。ctx.fireChannelRead(msg)表示通知下層處理器處理,若不調用該方法,讀事件將終止傳播到下游處理器。

public class NettyDemoServer {

	public static void main(String[] args) {
		ServerBootstrap serverBootstrap = new ServerBootstrap();
		serverBootstrap.group(new NioEventLoopGroup(), new NioEventLoopGroup()).channel(NioServerSocketChannel.class)
				.childHandler(new ChannelInitializer<NioSocketChannel>() {
					@Override
					protected void initChannel(NioSocketChannel ch) throws Exception {
						ch.pipeline().addLast(new StringDecoder()).addLast(new SimpleChannelInboundHandler<Object>() {
							@Override
							protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
								System.out.println("Handler1:" + msg);
								ctx.fireChannelRead(msg);
							}
						}).addLast(new SimpleChannelInboundHandler<Object>() {
							@Override
							protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
								System.out.println("Handler2:" + msg);
								ctx.fireChannelRead(msg);
							}

						});
					}
				}).bind(8080).addListener(o -> {
					if(o.isSuccess()){
						System.out.println("啟動成功");
					}
				});
	}
}

    2、client端

    客戶端以字符串的方式編碼,每隔三秒寫一條數據到服務端

public class NettyDemoClient {

	public static void main(String[] args)  {
		Bootstrap bootstrap = new Bootstrap();
		NioEventLoopGroup group = new NioEventLoopGroup();
		bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {
			@Override
			protected void initChannel(Channel ch) {
				ch.pipeline().addLast(new StringEncoder());
			}
		});
		Channel channel = bootstrap.connect("localhost", 8080).channel();
		while (true) {
			channel.writeAndFlush(new Date().toLocaleString() + ":測試netty");
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

    運行效果如下:

啟動成功
Handler1:2020-9-11 17:23:19:測試netty
Handler2:2020-9-11 17:23:19:測試netty
Handler1:2020-9-11 17:23:23:測試netty
Handler2:2020-9-11 17:23:23:測試netty
Handler1:2020-9-11 17:23:26:測試netty
Handler2:2020-9-11 17:23:26:測試netty

    Netty將IO處理細節全部屏蔽,業務開發時只需要定義不用入站和出站處理器處理對應的業務,實現了業務和通訊的解耦。

二、數據處理通道pipeline和通道處理器channelHandler

    1、channelHandler

netty的maven怎么配置

   繼承于ChannelHandler有兩大接口,ChannelInboundHandler和ChannelOutBoundHandler,分別代表入站和出站接口,對于如站處理器,當有消息進來時channelRead(ChannelHandlerContext ctx, Object msg) 方法會觸發,對于出站處理器,當向外寫出數據時write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)會被觸發。 ChannelInboundHandlerAdapter和ChanneloutBoundHandlerAdapter則是對兩類接口的通用實現。里面都是一些非常簡單的實現,僅僅將讀寫事件在pipeline中傳遞下去。

    2、pipeline的事件傳播順序

   對于入站處理器,執?順序與addLast添加的順序保持?致,前面打印的例子中已經驗證了這一點,對于出站處理器,執行順序與addLast添加的順序相反。下面我們在client端來驗證這一點,在client端添加兩個出站處理器。

public class NettyDemoClient {

	public static void main(String[] args) {
		Bootstrap bootstrap = new Bootstrap();
		NioEventLoopGroup group = new NioEventLoopGroup();
		bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {
			@Override
			protected void initChannel(Channel ch) {
				ch.pipeline().addLast(new StringEncoder()).addLast(new OutBoundHandlerFirst()).addLast(new OutBoundHandlerSecond());
			}
		});
		Channel channel = bootstrap.connect("localhost", 8080).channel();
		while (true) {
			channel.writeAndFlush(new Date().toLocaleString() + ":測試netty");
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static class OutBoundHandlerFirst extends ChannelOutboundHandlerAdapter {
		@Override
		public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
			System.out.println("OutBoundHandlerFirst");
			super.write(ctx, msg, promise);
		}
	}

	public static class OutBoundHandlerSecond extends ChannelOutboundHandlerAdapter {
		@Override
		public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
			System.out.println("OutBoundHandlerSecond");
			super.write(ctx, msg, promise);
		}
	}
}

    打印日志如下:

OutBoundHandlerSecond
OutBoundHandlerFirst
OutBoundHandlerSecond
OutBoundHandlerFirst
OutBoundHandlerSecond
OutBoundHandlerFirst
OutBoundHandlerSecond
OutBoundHandlerFirst
OutBoundHandlerSecond
OutBoundHandlerFirst

    這里就驗證了出站處理器,執行順序與addLast添加的順序相反。

    pipeline實際上是維持了一個雙向鏈表,為什么會出現這種現象呢?我們在AbstractChannelHandlerContext找到了答案,findContextInbound方法是拿next節點,而findContextOutbound是拿前一個節點

 private AbstractChannelHandlerContext findContextInbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.next;
        } while (!ctx.inbound);
        return ctx;
    }

    private AbstractChannelHandlerContext findContextOutbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);
        return ctx;
    }

三、處理器的生命周期

    當連接建立時,handlerAdded->channelRegistered->channelActive->channelRead->channelReadComplete

    當連接關閉時,channelInactive->channelUnregistered->handlerRemoved

    說明:channelRead和channelReadComplete每次讀完一次完整的數據包時,這兩個方法都會被調用

四、拆包粘包解決

    TCP協議是一個流式協議,所以在傳輸數據時,并不會按照我們的業務來傳輸一個完整的包,可能出現多個包一起發送,這時候接收端就要進行拆包,也可以出現把一個完整的包拆成多個小包來傳輸,這時候接收端需要把多個包合并成一個完整包來解析。那么netty有哪些方案呢?

    1、定長拆包器FixedLengthFrameDecoder

    每個數據包都固定長度,比方說每個數據包都是50,適用與簡單的場景

    2、行拆包器LineBasedFrameDecoder

    用換行符來進行拆包

    3、分隔符拆包器 DelimiterBasedFrameDecoder

    這個是分割符拆包器類似,只不過可以自定義特殊符號進行拆包,例如# @等符號,使用的時候必須確保正式報文中沒有這些特殊符號

    4、長度域拆包器 LengthFieldBasedFrameDecoder

    這是一種最通用的拆包器,幾乎所有的二進制自定義協議都可以基于這種拆包器來進行拆包,只要協議頭中定義一個長度域即可,比方說用4字節存儲消息body的長度

到此,相信大家對“netty的maven怎么配置”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿鲁科尔沁旗| 新民市| 樟树市| 平昌县| 克拉玛依市| 宝坻区| 辽阳县| 巨鹿县| 武川县| 运城市| 北川| 那曲县| 新建县| 大连市| 汉沽区| 玛纳斯县| 渭源县| 民乐县| 高邮市| 花莲市| 淮南市| 南岸区| 阿坝| 清河县| 桐庐县| 进贤县| 缙云县| 红原县| 蒲江县| 江油市| 广州市| 江陵县| 奉节县| 始兴县| 贵港市| 来凤县| 新乐市| 嘉黎县| 新密市| 肥乡县| 灵川县|