社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
什么是netty?
哪些中间件用到了netty?
最核心的三大组件 缓冲(Buffer)通道(Channel)事件模型(Event Model)
netty的前身可以当成是IO编程模型,当时IO编程模型出现了各种问题,
当时为了解决这些问题,jdk1.4之后便提出了 NIO,由于原生的java NIO编程复杂、效率低等缺点,就泛生出了netty这个编程模型,netty就是对NIO的一种封装。整体架构的变化如下图所示:
也就是下面这样,当selectot的线程池为1时,netty模型就相当于reactor中的多线程模型;假如为多个时,就是一个netty模型就相当于reactor中的主从多线程模型。
netty的线程模型可以参照Reactor设计模式中的三个,单线程Reactor模式、多线程Reactor模式、多Reactor模式,架构图如下图所示:
单线程Reactor模式
多线程Reactor模式
多Reactor模式
netty对原生NIO封装后,
netty的组件
组件之间,比如Channel、EventLoop与EventLoopGroup之间有如下关系:
netty简单实现一个RPC Server的结构是下图这样的,整体结构也是由上面的几个组件组合而成,代码就放ServerbootStrap的部分代码了,注释比较详细,仅供理解。
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
/**
*功能还是实现了,RPC 的目的就是允许像调用本地服务一样调用远程服务,
*需要对使用者透明,于是我们使用了动态代理。并使用 Netty 的 handler 发送数据和响应数据,
*完成了一次简单的 RPC 调用。
* 一个EventLoop在它的生命周期内只和一个Thread绑定,所有有EventLoop处理的IO事件都将在它专有的Thread上被处理。一个channel在它的生命周期内只注册一个
* EventLoop,每一个EventLoop负责处理一个或者多个Channel。
*
* @author chain
*
*/
public class ServerBootStrap {
private static void startServer0(String hostName, int port) {
// NioEventLoopGroup的bossGroup可以设置数量的,默认为this(0);
// bossGroup继承自线程池,维护了NioServerSocketChannel的实例;负责连接,开销小,连接成功后将这个SocketChannel转发给workerGroup。workerGroup会选出一个eventLoop
// 去维护这个socketChannel并注册到其维护的selector中,然后对其进行后续的IO事件处理。
// 当bossGroup的数量设置为1时,netty模型就相当于reactor中的多线程模型
// 当bossGroup的数量设置为多个时(比如4个),netty模型就相当于reactor中的主从多线程模型
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
// 当设置一个EventLoopGroup时,看源码仍然是绑定了bossGroup和workerGroup,只不过是同一个EventLoopGroup而已,
// 这就相当于Reactor的单线程模型
bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
// channelPipeline中每一个channelhandler都是通过它的eventLoop来传递给他的事件的,至关重要的是不要阻塞这个线程。
// 有的可以在添加pipline的时候也指定EventExecutorGroup去处理,channelHandler中所有的方法都会在这个指定的EventExecutorGroup中运行
// p.addLast(workerGroup, "handler", new StringEncoder());
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 执行顺序为注册的逆序
ChannelPipeline p = ch.pipeline();
p.addLast(new StringDecoder());
p.addLast(new StringEncoder());
p.addLast(new DealMesHandler());
p.addLast(new HelloServerHandler());
}
});
ChannelFuture future = bootstrap.bind(hostName, port).sync();
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
ServerBootStrap netBootStrap = new ServerBootStrap();
netBootStrap.startServer0("localhost", 8081);
}
}
补:忘了放一张比较经典的图:
最后,简介部分还有些面试题,可参考博文:netty面试常见问题
参考:
https://blog.csdn.net/wozniakzhang/article/details/92174287
https://blog.csdn.net/eric_sunah/article/details/80424344
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!