区块链技术博客
www.b2bchain.cn

剖析面试最常见问题之 Netty(下)求职学习资料

本文介绍了剖析面试最常见问题之 Netty(下)求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

Reactor线程模型

👨‍💻面试官 :大部分网络框架都是基于 Reactor 模式设计开发的。你先聊聊 Reactor线程模型吧!

🙋 :好的呀!

Reactor是一种经典的线程模型,Reactor模式基于事件驱动,特别适合处理海量的I/O事件。

Reactor线程模型分为单线程模型、多线程模型以及主从多线程模型。

以下图片来源于网络,原出处不明,如有侵权请联系我。

单线程Reactor

所有的IO操作都由同一个NIO线程处理。

剖析面试最常见问题之 Netty(下)

单线程Reactor

单线程 Reactor 的优点是对系统资源消耗特别小,但是,没办法支撑大量请求的应用场景并且处理请求的时间可能非常慢,毕竟只有一个线程在工作嘛!所以,一般实际项目中不会使用单线程Reactor 。

为了解决这些问题,演进出了Reactor多线程模型。

多线程Reactor

一个线程负责接受请求,一组NIO线程处理IO操作。

剖析面试最常见问题之 Netty(下)

多线程Reactor

大部分场景下多线程Reactor模型是没有问题的,但是在一些并发连接数比较多(如百万并发)的场景下,一个线程负责接受客户端请求就存在性能问题了。

为了解决这些问题,演进出了主从多线程Reactor模型。

主从多线程Reactor

一组NIO线程负责接受请求,一组NIO线程处理IO操作。

剖析面试最常见问题之 Netty(下)

主从多线程

Netty 线程模型了解么?

👨‍💻面试官 :说一下 Netty 线程模型吧!

🙋 :大部分网络框架都是基于 Reactor 模式设计开发的。

Reactor 模式基于事件驱动,采用多路复用将事件分发给相应的 Handler 处理,非常适合处理海量 IO 的场景。

在 Netty 主要靠 NioEventLoopGroup 线程池来实现具体的线程模型的 。

我们实现服务端的时候,一般会初始化两个线程组:

  1. bossGroup :接收连接。
  2. workerGroup :负责具体的处理,交由对应的 Handler 处理。

下面我们来详细看一下 Netty 中的线程模型吧!

单线程模型

一个线程需要执行处理所有的 acceptreaddecodeprocessencodesend 事件。对于高负载、高并发,并且对性能要求比较高的场景不适用。

对应到 Netty 代码是下面这样的

使用 NioEventLoopGroup 类的无参构造函数设置线程数量的默认值就是 CPU 核心数 *2

  //1.eventGroup既用于处理客户端连接,又负责具体的处理。   EventLoopGroup eventGroup = new NioEventLoopGroup(1);   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();             boobtstrap.group(eventGroup, eventGroup)             //......

多线程模型

一个 Acceptor 线程只负责监听客户端的连接,一个 NIO 线程池负责具体处理: acceptreaddecodeprocessencodesend 事件。满足绝大部分应用场景,并发连接量不大的时候没啥问题,但是遇到并发连接大的时候就可能会出现问题,成为性能瓶颈。

对应到 Netty 代码是下面这样的:

// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();   //3.给引导类配置两大线程组,确定了线程模型   b.group(bossGroup, workerGroup)     //......

剖析面试最常见问题之 Netty(下)

主从多线程模型

从一个 主线程 NIO 线程池中选择一个线程作为 Acceptor 线程,绑定监听端口,接收客户端连接的连接,其他线程负责后续的接入认证等工作。连接建立完成后,Sub NIO 线程池负责具体处理 I/O 读写。如果多线程模型无法满足你的需求的时候,可以考虑使用主从多线程模型 。

// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();   //3.给引导类配置两大线程组,确定了线程模型   b.group(bossGroup, workerGroup)     //......

剖析面试最常见问题之 Netty(下)

Netty 服务端和客户端的启动过程了解么?

服务端

        // 1.bossGroup 用于接收连接,workerGroup 用于具体的处理         EventLoopGroup bossGroup = new NioEventLoopGroup(1);         EventLoopGroup workerGroup = new NioEventLoopGroup();         try {             //2.创建服务端启动引导/辅助类:ServerBootstrap             ServerBootstrap b = new ServerBootstrap();             //3.给引导类配置两大线程组,确定了线程模型             b.group(bossGroup, workerGroup)                     // (非必备)打印日志                     .handler(new LoggingHandler(LogLevel.INFO))                     // 4.指定 IO 模型                     .channel(NioServerSocketChannel.class)                     .childHandler(new ChannelInitializer<SocketChannel>() {                         @Override                         public void initChannel(SocketChannel ch) {                             ChannelPipeline p = ch.pipeline();                             //5.可以自定义客户端消息的业务处理逻辑                             p.addLast(new HelloServerHandler());                         }                     });             // 6.绑定端口,调用 sync 方法阻塞知道绑定完成             ChannelFuture f = b.bind(port).sync();             // 7.阻塞等待直到服务器Channel关闭(closeFuture()方法获取Channel 的CloseFuture对象,然后调用sync()方法)             f.channel().closeFuture().sync();         } finally {             //8.优雅关闭相关线程组资源             bossGroup.shutdownGracefully();             workerGroup.shutdownGracefully();         }

简单解析一下服务端的创建过程具体是怎样的:

1.首先你创建了两个 NioEventLoopGroup 对象实例:bossGroupworkerGroup

  • bossGroup : 用于处理客户端的 TCP 连接请求。
  • workerGroup : 负责每一条连接的具体读写数据的处理逻辑,真正负责 I/O 读写操作,交由对应的 Handler 处理。

举个例子:我们把公司的老板当做 bossGroup,员工当做 workerGroup,bossGroup 在外面接完活之后,扔给 workerGroup 去处理。一般情况下我们会指定 bossGroup 的 线程数为 1(并发连接量不大的时候) ,workGroup 的线程数量为 CPU 核心数 2 。另外,根据源码来看,使用 NioEventLoopGroup 类的无参构造函数设置线程数量的默认值就是 CPU 核心数 2

2.接下来 我们创建了一个服务端启动引导/辅助类: ServerBootstrap,这个类将引导我们进行服务端的启动工作。

3.通过 .group() 方法给引导类 ServerBootstrap 配置两大线程组,确定了线程模型。

通过下面的代码,我们实际配置的是多线程模型,这个在上面提到过。

“`java
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

Reactor线程模型

👨‍💻面试官 :大部分网络框架都是基于 Reactor 模式设计开发的。你先聊聊 Reactor线程模型吧!

🙋 :好的呀!

Reactor是一种经典的线程模型,Reactor模式基于事件驱动,特别适合处理海量的I/O事件。

Reactor线程模型分为单线程模型、多线程模型以及主从多线程模型。

以下图片来源于网络,原出处不明,如有侵权请联系我。

单线程Reactor

所有的IO操作都由同一个NIO线程处理。

剖析面试最常见问题之 Netty(下)

单线程Reactor

单线程 Reactor 的优点是对系统资源消耗特别小,但是,没办法支撑大量请求的应用场景并且处理请求的时间可能非常慢,毕竟只有一个线程在工作嘛!所以,一般实际项目中不会使用单线程Reactor 。

为了解决这些问题,演进出了Reactor多线程模型。

多线程Reactor

一个线程负责接受请求,一组NIO线程处理IO操作。

剖析面试最常见问题之 Netty(下)

多线程Reactor

大部分场景下多线程Reactor模型是没有问题的,但是在一些并发连接数比较多(如百万并发)的场景下,一个线程负责接受客户端请求就存在性能问题了。

为了解决这些问题,演进出了主从多线程Reactor模型。

主从多线程Reactor

一组NIO线程负责接受请求,一组NIO线程处理IO操作。

剖析面试最常见问题之 Netty(下)

主从多线程

Netty 线程模型了解么?

👨‍💻面试官 :说一下 Netty 线程模型吧!

🙋 :大部分网络框架都是基于 Reactor 模式设计开发的。

Reactor 模式基于事件驱动,采用多路复用将事件分发给相应的 Handler 处理,非常适合处理海量 IO 的场景。

在 Netty 主要靠 NioEventLoopGroup 线程池来实现具体的线程模型的 。

我们实现服务端的时候,一般会初始化两个线程组:

  1. bossGroup :接收连接。
  2. workerGroup :负责具体的处理,交由对应的 Handler 处理。

下面我们来详细看一下 Netty 中的线程模型吧!

单线程模型

一个线程需要执行处理所有的 acceptreaddecodeprocessencodesend 事件。对于高负载、高并发,并且对性能要求比较高的场景不适用。

对应到 Netty 代码是下面这样的

使用 NioEventLoopGroup 类的无参构造函数设置线程数量的默认值就是 CPU 核心数 *2

  //1.eventGroup既用于处理客户端连接,又负责具体的处理。   EventLoopGroup eventGroup = new NioEventLoopGroup(1);   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();             boobtstrap.group(eventGroup, eventGroup)             //......

多线程模型

一个 Acceptor 线程只负责监听客户端的连接,一个 NIO 线程池负责具体处理: acceptreaddecodeprocessencodesend 事件。满足绝大部分应用场景,并发连接量不大的时候没啥问题,但是遇到并发连接大的时候就可能会出现问题,成为性能瓶颈。

对应到 Netty 代码是下面这样的:

// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();   //3.给引导类配置两大线程组,确定了线程模型   b.group(bossGroup, workerGroup)     //......

剖析面试最常见问题之 Netty(下)

主从多线程模型

从一个 主线程 NIO 线程池中选择一个线程作为 Acceptor 线程,绑定监听端口,接收客户端连接的连接,其他线程负责后续的接入认证等工作。连接建立完成后,Sub NIO 线程池负责具体处理 I/O 读写。如果多线程模型无法满足你的需求的时候,可以考虑使用主从多线程模型 。

// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();   //3.给引导类配置两大线程组,确定了线程模型   b.group(bossGroup, workerGroup)     //......

剖析面试最常见问题之 Netty(下)

Netty 服务端和客户端的启动过程了解么?

服务端

        // 1.bossGroup 用于接收连接,workerGroup 用于具体的处理         EventLoopGroup bossGroup = new NioEventLoopGroup(1);         EventLoopGroup workerGroup = new NioEventLoopGroup();         try {             //2.创建服务端启动引导/辅助类:ServerBootstrap             ServerBootstrap b = new ServerBootstrap();             //3.给引导类配置两大线程组,确定了线程模型             b.group(bossGroup, workerGroup)                     // (非必备)打印日志                     .handler(new LoggingHandler(LogLevel.INFO))                     // 4.指定 IO 模型                     .channel(NioServerSocketChannel.class)                     .childHandler(new ChannelInitializer<SocketChannel>() {                         @Override                         public void initChannel(SocketChannel ch) {                             ChannelPipeline p = ch.pipeline();                             //5.可以自定义客户端消息的业务处理逻辑                             p.addLast(new HelloServerHandler());                         }                     });             // 6.绑定端口,调用 sync 方法阻塞知道绑定完成             ChannelFuture f = b.bind(port).sync();             // 7.阻塞等待直到服务器Channel关闭(closeFuture()方法获取Channel 的CloseFuture对象,然后调用sync()方法)             f.channel().closeFuture().sync();         } finally {             //8.优雅关闭相关线程组资源             bossGroup.shutdownGracefully();             workerGroup.shutdownGracefully();         }

简单解析一下服务端的创建过程具体是怎样的:

1.首先你创建了两个 NioEventLoopGroup 对象实例:bossGroupworkerGroup

  • bossGroup : 用于处理客户端的 TCP 连接请求。
  • workerGroup : 负责每一条连接的具体读写数据的处理逻辑,真正负责 I/O 读写操作,交由对应的 Handler 处理。

举个例子:我们把公司的老板当做 bossGroup,员工当做 workerGroup,bossGroup 在外面接完活之后,扔给 workerGroup 去处理。一般情况下我们会指定 bossGroup 的 线程数为 1(并发连接量不大的时候) ,workGroup 的线程数量为 CPU 核心数 2 。另外,根据源码来看,使用 NioEventLoopGroup 类的无参构造函数设置线程数量的默认值就是 CPU 核心数 2

2.接下来 我们创建了一个服务端启动引导/辅助类: ServerBootstrap,这个类将引导我们进行服务端的启动工作。

3.通过 .group() 方法给引导类 ServerBootstrap 配置两大线程组,确定了线程模型。

通过下面的代码,我们实际配置的是多线程模型,这个在上面提到过。

“`java
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

Reactor线程模型

👨‍💻面试官 :大部分网络框架都是基于 Reactor 模式设计开发的。你先聊聊 Reactor线程模型吧!

🙋 :好的呀!

Reactor是一种经典的线程模型,Reactor模式基于事件驱动,特别适合处理海量的I/O事件。

Reactor线程模型分为单线程模型、多线程模型以及主从多线程模型。

以下图片来源于网络,原出处不明,如有侵权请联系我。

单线程Reactor

所有的IO操作都由同一个NIO线程处理。

剖析面试最常见问题之 Netty(下)

单线程Reactor

单线程 Reactor 的优点是对系统资源消耗特别小,但是,没办法支撑大量请求的应用场景并且处理请求的时间可能非常慢,毕竟只有一个线程在工作嘛!所以,一般实际项目中不会使用单线程Reactor 。

为了解决这些问题,演进出了Reactor多线程模型。

多线程Reactor

一个线程负责接受请求,一组NIO线程处理IO操作。

剖析面试最常见问题之 Netty(下)

多线程Reactor

大部分场景下多线程Reactor模型是没有问题的,但是在一些并发连接数比较多(如百万并发)的场景下,一个线程负责接受客户端请求就存在性能问题了。

为了解决这些问题,演进出了主从多线程Reactor模型。

主从多线程Reactor

一组NIO线程负责接受请求,一组NIO线程处理IO操作。

剖析面试最常见问题之 Netty(下)

主从多线程

Netty 线程模型了解么?

👨‍💻面试官 :说一下 Netty 线程模型吧!

🙋 :大部分网络框架都是基于 Reactor 模式设计开发的。

Reactor 模式基于事件驱动,采用多路复用将事件分发给相应的 Handler 处理,非常适合处理海量 IO 的场景。

在 Netty 主要靠 NioEventLoopGroup 线程池来实现具体的线程模型的 。

我们实现服务端的时候,一般会初始化两个线程组:

  1. bossGroup :接收连接。
  2. workerGroup :负责具体的处理,交由对应的 Handler 处理。

下面我们来详细看一下 Netty 中的线程模型吧!

单线程模型

一个线程需要执行处理所有的 acceptreaddecodeprocessencodesend 事件。对于高负载、高并发,并且对性能要求比较高的场景不适用。

对应到 Netty 代码是下面这样的

使用 NioEventLoopGroup 类的无参构造函数设置线程数量的默认值就是 CPU 核心数 *2

  //1.eventGroup既用于处理客户端连接,又负责具体的处理。   EventLoopGroup eventGroup = new NioEventLoopGroup(1);   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();             boobtstrap.group(eventGroup, eventGroup)             //......

多线程模型

一个 Acceptor 线程只负责监听客户端的连接,一个 NIO 线程池负责具体处理: acceptreaddecodeprocessencodesend 事件。满足绝大部分应用场景,并发连接量不大的时候没啥问题,但是遇到并发连接大的时候就可能会出现问题,成为性能瓶颈。

对应到 Netty 代码是下面这样的:

// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理 EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();   //3.给引导类配置两大线程组,确定了线程模型   b.group(bossGroup, workerGroup)     //......

剖析面试最常见问题之 Netty(下)

主从多线程模型

从一个 主线程 NIO 线程池中选择一个线程作为 Acceptor 线程,绑定监听端口,接收客户端连接的连接,其他线程负责后续的接入认证等工作。连接建立完成后,Sub NIO 线程池负责具体处理 I/O 读写。如果多线程模型无法满足你的需求的时候,可以考虑使用主从多线程模型 。

// 1.bossGroup 用于接收连接,workerGroup 用于具体的处理 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try {   //2.创建服务端启动引导/辅助类:ServerBootstrap   ServerBootstrap b = new ServerBootstrap();   //3.给引导类配置两大线程组,确定了线程模型   b.group(bossGroup, workerGroup)     //......

剖析面试最常见问题之 Netty(下)

Netty 服务端和客户端的启动过程了解么?

服务端

        // 1.bossGroup 用于接收连接,workerGroup 用于具体的处理         EventLoopGroup bossGroup = new NioEventLoopGroup(1);         EventLoopGroup workerGroup = new NioEventLoopGroup();         try {             //2.创建服务端启动引导/辅助类:ServerBootstrap             ServerBootstrap b = new ServerBootstrap();             //3.给引导类配置两大线程组,确定了线程模型             b.group(bossGroup, workerGroup)                     // (非必备)打印日志                     .handler(new LoggingHandler(LogLevel.INFO))                     // 4.指定 IO 模型                     .channel(NioServerSocketChannel.class)                     .childHandler(new ChannelInitializer<SocketChannel>() {                         @Override                         public void initChannel(SocketChannel ch) {                             ChannelPipeline p = ch.pipeline();                             //5.可以自定义客户端消息的业务处理逻辑                             p.addLast(new HelloServerHandler());                         }                     });             // 6.绑定端口,调用 sync 方法阻塞知道绑定完成             ChannelFuture f = b.bind(port).sync();             // 7.阻塞等待直到服务器Channel关闭(closeFuture()方法获取Channel 的CloseFuture对象,然后调用sync()方法)             f.channel().closeFuture().sync();         } finally {             //8.优雅关闭相关线程组资源             bossGroup.shutdownGracefully();             workerGroup.shutdownGracefully();         }

简单解析一下服务端的创建过程具体是怎样的:

1.首先你创建了两个 NioEventLoopGroup 对象实例:bossGroupworkerGroup

  • bossGroup : 用于处理客户端的 TCP 连接请求。
  • workerGroup : 负责每一条连接的具体读写数据的处理逻辑,真正负责 I/O 读写操作,交由对应的 Handler 处理。

举个例子:我们把公司的老板当做 bossGroup,员工当做 workerGroup,bossGroup 在外面接完活之后,扔给 workerGroup 去处理。一般情况下我们会指定 bossGroup 的 线程数为 1(并发连接量不大的时候) ,workGroup 的线程数量为 CPU 核心数 2 。另外,根据源码来看,使用 NioEventLoopGroup 类的无参构造函数设置线程数量的默认值就是 CPU 核心数 2

2.接下来 我们创建了一个服务端启动引导/辅助类: ServerBootstrap,这个类将引导我们进行服务端的启动工作。

3.通过 .group() 方法给引导类 ServerBootstrap 配置两大线程组,确定了线程模型。

通过下面的代码,我们实际配置的是多线程模型,这个在上面提到过。

“`java
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 剖析面试最常见问题之 Netty(下)求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们