Netty相关网络IO面试题(20题)

写在前面:
本文2万多字,阅读需要花费一点时间, 主要介绍网络编程部分知识,包括Netty 和 IO 网络等知识点;
仅供复习使用!

1. 网络四元组

四元组,简单理解就是在 TCP 协议中,去确定一个客户端连接的组成要素,它包括源IP 地址、目标 IP 地址、源端口号、目标端口号。
正常情况下,我们对于网络通信的认识可能是这样(如图)。
服务端通过 ServerSocket 建立一个对指定端口号的监听,比如 8080。 客户端通过目标 ip 和端口就可以和服务端建立一个连接,然后进行数据传输。
image.png
但是我们知道的是,一个 Server 端可以接收多个客户端的连接,比如像这种情况(如图)。
那,当多个客户端连接到服务端的时候,服务端需要去识别每一个连接
image.png
并且(如图),TCP 是全双工协议,也就是说数据允许在连接的两个方向上同时传输,因此这里的客户端,如果是反向通信,它又变成了服务端
image.png
所以基于这两个原因,就引入了四元组的设计,也就是说,当一个客户端和服务端建立一个 TCP 连接的时候,通过源 IP 地址、目标 IP 地址、源端口号、目标端口号来确定一个唯一的 TCP 连接。因为服务器的 IP 和端口是不变的,只要客户端的 IP 和端口彼此不同就 OK 了。
比如像这种情况(如图),同一个客户端主机上有三个连接连到 Server 端,那么这个时候源 IP 相同,源端口号不同。此时建立的四元组就是(10.23.15.3,59461 ,192.168.8.135,8080)
其中,源端口号是每次建立连接的时候系统自动分配的。
image.png
:::info
“终局思维”来看待自己的职业规划
:::

2. 对 Netty 的认识

好的,我用三点来简单的介绍下 Netty

  1.  第一:Netty 是一个 基于 NIO 模型的高性能网络通信框架,其实可以认为它是对 NIO 网络模。型的封装,提供了简单易用的 API,我们可以利用这些封装好的API 快速开发自己的网络程序。
  2.  第二:Netty 在 NIO 的基础上做了很多优化,比如零拷贝机制、高性能无锁队列、内存池等,因此性能会比 NIO 更高。
  3.  第三:Netty 可以支持多种通信协议,如 Http、WebSocket 等,并且针对数据通信的拆包黏包问题,Netty 内置了拆包策略。

为什么要用 Netty

Nety 相比于直接使用 JDK 自带的 NIO 相关的 API 来说更加易用

  1. 统一的 API,支持多种传输类型,如阻塞、非阻塞,以及 epoll、poll 等模型。
  2. 我们可以使用非常少的代码来实现,多线程 Reactor 模型以及主从多线程 Reactor模型
  3. 自带编解码器解决 TCP 粘包/拆包问题。
  4. 自带各种协议栈。
  5. 比直接使用 Java 库中的 NIO API 有更高的吞吐量、更低的延迟、更低的资源消耗和更少的内存复制。
  6. 安全性不错,有完整的 SSL/TLS 以及 StartTLS 支持。
  7. 社区活跃成熟稳定,经历了大型项目的使用和考验,而且很多开源项目都使用到了Netty, 比如我们经常接触的 Dubbo、RocketMQ ZK 等等。

Netty 可以做什么事情

核心点还是在于解决服务器如何承载更多的用户同时访问
传统的 BIO 模型,由于阻塞的特性,使得在高并发场景中,很难获得更高的吞吐量。
而后来基于 NIO 的多路复用模型虽然在阻塞方面进行了优化,但是它的 API 使用比较复杂,对于初学者来说使用不是很友好。而 Netty 是基于 NIO 的封装,提供了成熟且简单易用的 API,降低了使用成本和学习成本。
本质上来说,Netty 和 NIO 所扮演的角色是相同的,都是为提升服务端的吞吐量,让用户获得更好的产品体验。
另外,Netty 这个中间件经过很多年验证,在目前主流中间件如 Zookeeper、Dubbo、RocketMQ 中都有应用。

3. Netty 核心组件和作用

高手:Netty 由三层结构构成:网络通信层、事件调度器与服务编排层
在网络通信层有三个核心组件:Bootstrap、ServerBootStrap、Channel
 Bootstrap 负责客户端启动并用来链接远程 netty server
 ServerBootStrap 负责服务端监听,用来监听指定端口,
 Channel 是负责网络通信的载体
事件调度器有两个核心组件:EventLoopGroup 与 EventLoop
 EventLoopGroup 本质上是一个线程池,主要负责接收 I/O 请求,并分配线程执行处理请求。
 EventLoop。相当于线程池中的线程
在服务编排层有三个核心组件 ChannelPipeline、ChannelHandler、ChannelHandlerContext
 ChannelPipeline 负责将多个 Channelhandler 链接在一起
 ChannelHandler 针对 IO 数据的处理器,数据接收后,通过指定的 Handler 进行处理。
 ChannelHandlerContext 用来保存 ChannelHandler 的上下文信息

Netty 有几种线程模型吧?

Netty 提供了三种 Reactor 模型的支持
 单线程单 Reactor 模型
 多线程单 Reactor 模型
 多线程多 Reactor 模型

对于这三种线程 Reactor 模型的理解

Reactor 模型有三个重要的组件:

  1. Reactor :将 I/O 事件发派给对应的 Handler
  2. Acceptor :处理客户端连接请求
  3. Handlers :执行非阻塞读/写
    这是最基本的单 Reactor 单线程模型
    image.png
    其中 Reactor 线程,负责多路分离套接字,有新连接到来触发 connect 事件之后,交
    由 Acceptor 进行处理,有 IO 读写事件之后交给 hanlder 处理。
    Acceptor 主要任务就是构建 handler ,在获取到和 client 相关的 SocketChannel 之
    后 ,绑定到相应的 hanlder 上,对应的 SocketChannel 有读写事件之后,基于 racotor
    分发,hanlder 就可以处理了(所有的 IO 事件都绑定到 selector 上,有 Reactor 分发)
    多线程单 Reactor 模型
    单线程 Reactor 这种实现方式有存在着缺点,从实例代码中可以看出,handler 的执行
    是串行的,如果其中一个 handler 处理线程阻塞将导致其他的业务处理阻塞。由于
    handler 和 reactor 在同一个线程中的执行,这也将导致无法接收新的请求。
    为了解决这种问题,有人提出使用多线程的方式来处理业务,也就是在业务处理的地方
    加入线程池异步处理,将 reactor 和 handler 在不同的线程来执行,这就是多线程单
    Reactor 模型
    image.png
    多线程多 Reactor 模型
    在多线程单 Reactor 模型中,所有的 I/O 操作是由一个 Reactor 来完成,而 Reactor
    运行在单个线程中,它需要处理包括 Accept()/read()/write/connect 操作,对于小容
    量的场景,影响不大。但是对于高负载、大并发或大数据量的应用场景时,容易成为瓶
    颈,主要原因如下:
     一个 NIO 线程同时处理成百上千的链路,性能上无法支撑,即便 NIO 线程的 CPU
    负荷达到 100%,也无法满足海量消息的读取和发送;
     当 NIO 线程负载过重之后,处理速度将变慢,这会导致大量客户端连接超时,超
    时之后往往会进行重发,这更加重了 NIO 线程的负载,最终会导致大量消息积压
    和处理超时,成为系统的性能瓶颈;
    所以,我们还可以更进一步优化,引入多 Reactor 多线程模式
    image.png
    Main Reactor 负责接收客户端的连接请求,然后把接收到的请求传递给
    SubReactor(其中 subReactor 可以有多个),具体的业务 IO 处理由 SubReactor
    完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值