在 Netty 以及 NIO 出现之前,我们写 IO 应用其实用的 都是用 java.io.* 下所提供的包。比如下面的伪代码:
ServeSocket serverSocket = new ServeSocket(8080);
Socket socket = serverSocket.accept() ;
BufferReader in = .... ;
String request ;
while((request = in.readLine()) != null){
new Thread(new Task()).start()
}
大概是这样,其实主要想表达的是:这样一个线程只能处 理一个连接。 如果是 100 个客户端连接那就得开 100 个线程,1000 那就得 1000 个线程。要知道线程资源非常宝贵,每次的创建都会带来消耗,而且每个线程还得为它分配对应的栈内存。
即便是我们给 JVM 足够的内存,大量线程所带来的上下文切换也是受不了的。并且传统 IO 是阻塞模式,每一次的响应必须的是发起 IO 请求,处理请求完成再同时返回,直接的结果就是性能差,吞吐量低。
Reactor 模型
单线程

从图中可以看出:
它是由一个线程来接收客户端的连接,并将该请求分发到对应的事件处理 handler 中,整个过程完全是异步非阻塞的;并且完全不存在共享资源的问题。所以理论上来说吞 吐量也还不错。
多线程

其实最大的改进就是将原有的事件处理改为了多线程。可以基于 Java 自身的线程池实现,这样在大量请求的处理上性能提升是巨大的。
虽然如此,但理论上来说依然有一个地方是单点的;那就是处理客户端连接的线程。因为大多数服务端应用或多或少在连接时都会处理一些业务,如鉴权之类的,当连接的客户端越来越多时这一个线程依然会存在性能问题。于是又有了下面的线程模型。
主从多线程

该模型将客户端连接那一块的线程也改为多线程,称为主线程。同时也是多个子线程来处理事件响应,这样无论是连接还是事件都是高性能的。
Netty 实现
private EventLoopGroup boss = new NioEventLoopGroup();
private EventLoopGroup work = new NioEventLoopGroup();
/**
* 启动 Netty
** @return
* @throws InterruptedException
*/
@PostConstruct
public void start() throws InterruptedException {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss, work)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(nettyPort))
//保持长连接
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new HeartbeatInitializer());
ChannelFuture future = bootstrap.bind().sync();
if (future.isSuccess()) {
LOGGER.info("启动 Netty 成功");
}
}
其实这里的boss就相当于Reactor模型中处理客户端连接的线程池。work自然就是处理事件的线程池了。那么如何来实现上文的三种模式呢?其实也很简单:
private EventLoopGroup group = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(group)
.childHandler(new HeartbeatInitializer());
多线程模型:
private EventLoopGroup boss = new NioEventLoopGroup(1);
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss,work)
.childHandler(new HeartbeatInitializer());
主从多线程:
private EventLoopGroup boss = new NioEventLoopGroup();
private EventLoopGroup work = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap()
.group(boss,work)
.childHandler(new HeartbeatInitializer());
总结
其实看过了 Netty 的线程模型之后能否对我们平时做高性能应用带来点启发呢?
本文探讨了Netty在处理高性能IO应用时的线程模型,包括单线程、多线程和主从多线程模型。Netty通过Reactor模式实现异步非阻塞,利用线程池提高处理性能,避免上下文切换带来的损耗,确保高吞吐量。Boss线程池负责客户端连接,Worker线程池处理事件响应,这种设计适应大规模并发场景。
1060

被折叠的 条评论
为什么被折叠?



