赞
踩
什么是Netty?
Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。
1)本质:JBoss做的一个Jar包
2)目的:快速开发高性能、高可靠性的网络服务器和客户端程序
3)优点:提供异步的、事件驱动的网络应用程序框架和工具
通俗的说:一个好使的处理Socket的框架
Netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(Blocking I/O,阻塞IO),他的并发性能得到了很大提高。
Netty的传输快其实也是依赖了NIO的一个特性——零拷贝。
我们知道,Java的内存有堆内存、栈内存和字符串常量池等等,其中堆内存是占用内存空间最大的一块,也是Java对象存放的地方,一般我们的数据如果需要从IO读取到堆内存,中间需要经过Socket缓冲区,也就是说一个数据会被拷贝两次才能到达他的的终点,如果数据量大,就会造成不必要的资源浪费。
Netty针对这种情况,使用了NIO中的另一大特性——零拷贝,当他需要接收数据的时候,他会在堆内存之外开辟一块内存,数据就直接从IO读到了那块内存中去,在netty里面通过ByteBuf可以直接对这些数据进行直接操作,从而加快了传输速度。
Channel
接口是 Netty 对网络操作抽象类,它除了包括基本的 I/O 操作,如 bind()
、connect()
、read()
、write()
等。
比较常用的Channel
接口实现类是NioServerSocketChannel
(服务端)和NioSocketChannel
(客户端),这两个 Channel
可以和 BIO 编程模型中的ServerSocket
以及Socket
两个概念对应上。Netty 的 Channel
接口所提供的 API,大大地降低了直接使用 Socket 类的复杂性。
这么说吧!EventLoop
(事件循环)接口可以说是 Netty 中最核心的概念了!
《Netty 实战》这本书是这样介绍它的:
EventLoop
定义了 Netty 的核心抽象,用于处理连接的生命周期中所发生的事件。
是不是很难理解?说实话,我学习 Netty 的时候看到这句话是没太能理解的。
说白了,EventLoop
的主要作用实际就是负责监听网络事件并调用事件处理器进行相关 I/O 操作的处理。
那 Channel
和 EventLoop
直接有啥联系呢?
Channel
为 Netty 网络操作(读写等操作)抽象类,EventLoop
负责处理注册到其上的Channel
处理 I/O 操作,两者配合参与 I/O 操作。
Netty 是异步非阻塞的,所有的 I/O 操作都为异步的。
因此,我们不能立刻得到操作是否执行成功,但是,你可以通过 ChannelFuture
接口的 addListener()
方法注册一个 ChannelFutureListener
,当操作执行成功或者失败时,监听就会自动触发返回结果。
并且,你还可以通过ChannelFuture
的 channel()
方法获取关联的Channel
public interface ChannelFuture extends Future<Void> {
Channel channel();
ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> var1);
......
ChannelFuture sync() throws InterruptedException;
}
另外,我们还可以通过 ChannelFuture
接口的 sync()
方法让异步的操作变成同步的。
下面这段代码使用过 Netty 的小伙伴应该不会陌生,我们指定了序列化编解码器以及自定义的 ChannelHandler
处理消息。
b.group(eventLoopGroup)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new NettyKryoDecoder(kryoSerializer, RpcResponse.class));
ch.pipeline().addLast(new NettyKryoEncoder(kryoSerializer, RpcRequest.class));
ch.pipeline().addLast(new KryoClientHandler());
}
});
ChannelHandler
是消息的具体处理器。他负责处理读写操作、客户端连接等事情。
ChannelPipeline
为 ChannelHandler
的链,提供了一个容器并定义了用于沿着链传播入站和出站事件流的 API 。当 Channel
被创建时,它会被自动地分配到它专属的 ChannelPipeline
。
我们可以在 ChannelPipeline
上通过 addLast()
方法添加一个或者多个ChannelHandler
,因为一个数据或者事件可能会被多个 Handler 处理。当一个 ChannelHandler
处理完之后就将数据交给下一个 ChannelHandler
。
EventLoopGroup
包含多个 EventLoop
(每一个 EventLoop
通常内部包含一个线程),上面我们已经说了 EventLoop
的主要作用实际就是负责监听网络事件并调用事件处理器进行相关 I/O 操作的处理。
并且 EventLoop
处理的 I/O 事件都将在它专有的 Thread
上被处理,即 Thread
和 EventLoop
属于 1 : 1 的关系,从而保证线程安全。
Boss EventloopGroup、Worker EventloopGroup
上图是一个服务端对 EventLoopGroup
使用的大致模块图,其中 Boss EventloopGroup
用于接收连接,Worker EventloopGroup
用于具体的处理(消息的读写以及其他逻辑处理)。
从上图可以看出: 当客户端通过 connect
方法连接服务端时,bossGroup
处理客户端连接请求。当客户端处理完成后,会将这个连接提交给 workerGroup
来处理,然后 workerGroup
负责处理其 IO 相关操作。
Bootstrap
是客户端的启动引导类/辅助类,具体使用方法如下:
EventLoopGroup group = new NioEventLoopGroup();
try {
//创建客户端启动引导/辅助类:Bootstrap
Bootstrap b = new Bootstrap();
//指定线程模型
b.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。