Java面试题netty系列

Netty 

1、为什么要用 Netty 呢? 

因为 Netty 具有下面这些优点,并且相比于直接使用 JDK 自带的 NIO 相关的 API 来说更加易用。 

  统一的 API,支持多传输类型,阻塞和非阻塞的 

  简单而强大的线程模型。 

  自带编解码器解决 TCP 粘包/拆包问题 

  自带各种协议栈。 

  真正的无连接数据包套接字支持。 

  比直接使用 Java  API 有更高的吞吐量更低的延迟、更低的资源消耗和更少的内存

复制。 

  安全性不错,有完整的 SSL/TLS  StartTLS 支持 

  社区活跃 

 

成熟稳定,经历了大型项目的使用和考验,而且很多开源项目都使用到 Netty 比如我

们经常接触的 DubboRocketMQ 等等 

2Netty 有哪些应场景? 

理论上来说,NIO 可以做的事情 ,使 Netty 都可以做并且更好。Netty 主要用来做网络通信 : 

  作为 RPC 框架的网络通信工 :我们在分布式系统中,不同服务节点之间经常需要相互 调用,这个时候就需要 RPC 框架了。不同服务节点之间的通信是如何做的呢?可以使用  Netty 来做。比如我调用另外一个节点的方法的话,至少是要让对方知道我调用的是哪个 类中的哪个方法以及相关参数吧! 

  实现一个自己的 HTTP 服务器 :通 Netty 我们可以自己实现一个简单的 HTTP 服务 器,这个大家应该不陌生。说到 HTTP 服务器的话,作为 Java 开发,我们一般使  Tomcat 比较多。一个最基本的 HTTP 服务器可要以处理常见的 HTTP Method 的请求, 比如 POST 请求GET 请求等等。 

  实现一个即时通讯系统 :使用 Netty 我们以实现一个可以聊天类似微信的即时通讯系 统,这方面的开源项目还蛮多的,可以自行去 Github 找一找 

  实现消息推送系统 :市面上有很多消息推送系统都是基于 Netty 来做的。 

3Netty 的优势有些? 

  使用简单:封装了 NIO 的很多细节,使用更简单 

  功能强大:预置了多种编解码功能,支持多种主流协议。 

  定制能力强:可以通过 ChannelHandler 通信框架进行灵活地扩展。 

  性能高:通过与其他业界主流的 NIO 框架比,Netty 的综合性能最优 

  稳定:Netty 修复了已经发现的所有 NIO  bug,让开发人员可以专注于业务本身。 

  社区活跃:Netty 是活跃的开源项目,版本迭代周期短,bug 修复度快。 

3Netty 核心组件哪些?分别有什么作用? 

Channel 

Channel 接口是 Netty 对网络操作抽象类,它除了包括基本 I/O 操作,如 bind()connect()read()write() 等。 

比较常用Channel接口实现类NioServerSocketChannel务端)和

NioSocketChannel客户端),这两 Channel 可以和 BIO 模型中ServerSocket

Socket两个概念对应上。Netty  Channel 接口所提供 API,大大地降低了直接使

 Socket 类的复杂 

EventLoop 

EventLoop 的主要用实际就是负责监听网络事件并调用事件处理器进行相 I/O 操作

的处理。 

ChannelFuture 

Netty 是异步非阻塞的,所有的 I/O 操作都异步的。因此,我们不能立刻得到操作是否执行成功,但是,你可以通过 ChannelFuture 接口的 addListener() 方法注册一
 ChannelFutureListener,当操作执行成或者失败时,监听就会自动触发返回结果。 

ChannelHandler  ChannelPipeline 

ChannelHandler 息的具体处理器。他负责处理读写操作、客户端连接等事情  ChannelPipeline  ChannelHandler ,提供了一个容器并定义了用于沿着链传播入站和出站事件流的 API 。当 Channel 被创时,它会被自动地分配到它专属的
ChannelPipeline 

我们可以在 ChannelPipeline 上通 addLast() 方法添加一个或多个ChannelHandler 为一个数据或者事件可能会被多个 Handler 处理。当一个 ChannelHandler 处理完之后就将数据交给下一个 ChannelHandler  

5EventloopGroup 了解么? EventLoop 啥关系? 

EventLoopGroup 含多 EventLoop每一个 EventLoop 常内部包含一个线程),上面我们已经说了 EventLoop 的主作用实际就是负责监听网络事件并调用事件处理器进行相关 I/O 操作处理 

并且 EventLoop  I/O 事件都将在它有的 Thread 上被处,即 Thread  EventLoop 属于 1 : 1 的关系,从而保证线程安全。 

Boss EventloopGroup 用于接收连接Worker EventloopGroup 用于具体的处理(消息的读写以及其他逻辑处理)。 

当客户端通过 connect 方法连接服务端时bossGroup 处理客户连接请求。当客户端处理完成后,会将这个连接提交给 workerGroup 来处理,然 workerGroup 负责处理其 IO 相关操作。 

6、请说下对 Bootstrap  ServerBootstrap 的了解 

 

Bootstrap 通常使 connet() 方法连接到程的主机和端口,作为一个 Netty TCP 协议

通信中的客户端。另外,Bootstrap 也可以通过 bind() 方法绑定地的一个端口,作 UDP 协议通信中的一端 

  ServerBootstrap通常使用 bind() 方法绑本地的端口上,然后等待客户端的连接 

  Bootstrap 只需要配置一个线程 EventLoopGroup , ServerBootstrap需要配置两 个线程组— EventLoopGroup ,一个用于收连接,一个用于具体的处理。 

7、请说下 Netty 线模型? 

 Netty 主要靠 NioEventLoopGroup 线池来实现具体的线程模型的  我们实现服务端的时候,一般会初始化两个线程组: 

  bossGroup:接收连接。 

  workerGroup :负具体的处理,交由对应 Handler 处理。 

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

多线程模型 
一个 Acceptor 线程只负责监听客户端的连接,一个 NIO 线程池责具体处理 accept

readdecodeprocessencodesend 事件。满足绝大部分应用场景,并发连接量不大

的时候没啥问题,但是遇到并发连接大的时候就可能会出现问题,成为性能瓶颈 

主从多线程模型 
从一个 主线程 NIO 线程池中选择一个线程作 Acceptor 线程,绑定监听端口,接收客

户端连接的连接,其他线程负责后续的接入认证等工作。连接建立完成后Sub NIO 线

负责具体处理 I/O 。如果多线程模型无法满足你的需求的时候,可以考虑使用主从多线

程模型  

8Netty 服务端和户端的启动过程是怎样的? 

服务端 

1.  首先你创建了两个 NioEventLoopGroup 象实例:bossGroup  workerGroup 

  bossGroup : 用于处客户端的 TCP 连接请求。 

 

workerGroup :负每一条连接的具体读写数据的处理逻辑,真正负 I/O 读写操作,

交由对应的 Handler 处理。 

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

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

4.  channel()方法引导类 ServerBootstrap指定了 IO 模型NIO 

  NioServerSocketChannel :指定服务端的 IO 模型为 NIO,与 BIO 编程模型中的 ServerSocket对应。 

  NioSocketChannel : 指定客户端的 IO  NIO  BIO 模型中Socket对应 5.通过 .childHandler()给引导类创建一ChannelInitializer ,然制定了服务端消息的 业务处理逻辑 HelloServerHandler 6. ServerBootstrap 类的 bind()方法绑定 端口 

客户端 

  创建一个 NioEventLoopGroup 对象实 

  创建客户端启动的引导类是 Bootstrap 

  通过 .group() 方法引导类 Bootstrap 置一个线程组 

  channel()方法引导类 Bootstrap指定了 IO 模型NIO 

  通过 .childHandler()给引导类创建一ChannelInitializer ,然制定了客户端消息的业 务处理逻辑 HelloClientHandler  

  调用 Bootstrap 类的 connect()方法进行连接,这个方法需要指定两个参数 

  inetHost : ip  

  inetPort : 端口 

9、什么是 TCP /拆包? 

TCP 粘包/拆包 就是基于 TCP 发送数据的时候,出现了多个字符串“粘”在了一起或者一个字符串被“拆”开的问题。 

10、如何在 Netty 中解决 TCP 粘包问题 

1.  使用 Netty 自带的解码器 

  LineBasedFrameDecoder : 发送端发送数包的时候,每个数据包之间以换行符作为分 隔,LineBasedFrameDecoder 的工作原是它依次遍历 ByteBuf 中的可读字节,判断 是否有换行符,然后进行相应的截取。 

 

DelimiterBasedFrameDecoder : 可以自定分隔符解码器,

LineBasedFrameDecoder 实际上是一种殊的 DelimiterBasedFrameDecoder 解码器。 

  FixedLengthFrameDecoder: 固定长度解器,它能够按照指定的长度对消息进行相应 的拆包。LengthFieldBasedFrameDecoder 

2.  自定义序列化编解码器 
 Java 中自带的有 Serializable 接口实现序列化,但由于它性能、安全性等原因一般情况下是不会被使用到的。 

通常情况下,我们使用 ProtostuffHessian2json 序列方式比较,另外还有一些序列化性能非常好的序列化方式也是很好的选择: 

  专门针对 Java 语言KryoFST  

  跨语言的:Protostuff(基于 protobuf 而来),ProtoBufThriftAvro MsgPack  

11TCP 长连接和连接了解么? 

我们知道 TCP 在进行读写之前,server  client 之间必须提前建立一个连接。建立连接的过程,需要我们常说的三次握手,释放/关闭连接的话需要四次挥手。这个过程是比较消耗网络资源并且有时间延迟的。 

所谓,短连接说的就是 server   client 建立连接之后,读写完成之后就关闭掉连接,如果下一次再要互相发送消息,就要重新连接。短连接的优点很明显,就是管理和实现都比较简单,缺点也很明显,每一次的读写都要建立连接必然会带来大量网络资源的消耗,并且连接的建立也需要耗费时间。 

长连接说的就是 client  server 双方建立接之后,即使 client  server 完成一次读写,它们之间的连接并不会主动关闭,后续的读写操作会继续使用这个连接。长连接的可以省去较多的 TCP 建立和关闭的操作,降低对网络资源的依赖,节约时间。对于频繁请求资源的客户来说,非常适用长连接。 

12为什么需要心跳Netty 中心跳机了解么 

 TCP 保持长连接的过程中,可能会出现断网等网络异常出现,异常发生的时候 client  server 之间如果有交互的话,他们是无法发现对方已经掉线的。为了解决这个问, 我们就需要引入 心跳机制  

心跳机制的工作原理是:  client  server 间在一定时间内没有数据交互, 即处于 idle 状态时, 客户端服务器就会发送一个特殊的数据包给对, 当接收方收到这个数据报文后, 也立即发送一个特殊的数据报文, 回应发送方, 此即一个 PING-PONG 交互。所, 当某一端收到心跳消息后, 就知道了对方仍然在线, 这就确保 TCP 连接的有效性. 

TCP 实际上自带的就有长连接选项,本身是也有心跳包机制,也就 TCP 的选项:SO_KEEPALIVE。但是TCP 协议层面的长连接灵活性不够。所以,一般情况下我们都是在应用层协议上实现自定义信跳机制的,也就是在 Netty 层面通过编码实现。通 Netty 实现心跳机制的话,核心类是 IdleStateHandler  

13讲讲 Netty 的零拷贝 

零复制(英语:Zero-copy;也译零拷贝)术是指计算机执行操作时,CPU 不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节 CPU 周期和内存带宽。 

 OS 层面上的 Zero-copy 通常指避免在 户态(User-space)  内核态(Kernel-space) 之间来回拷贝数据。而在 Netty 层面 ,零贝主要体现在对于数据操作的优化。 

Netty 中的零拷贝体现在以下几个方面: 

  使用 Netty 提供的 CompositeByteBuf , 可以将多ByteBuf 并为一个逻辑上的  ByteBuf, 避免了各 ByteBuf 之间的拷贝 

  ByteBuf 支持 slice , 因此可以将 ByteBuf 分解为多个共享同个存储区域  ByteBuf, 避免了内存拷贝。 

  通过 FileRegion FileChannel.tranferTo 实现文件传, 以直接将文件缓冲区的 数据发送到目标 Channel, 避免了传统通过 write 方式导致的存拷贝问题. 

14Netty  Tomcat 的区别? 

  作用不同:Tomcat  Servlet 容器,可以 Web 服务器, Netty 是异步事件驱动 的网络应用程序框架和工具用于简化网络编程,例TCPUDP套接字服务器。 

  协议不同:Tomcat 是基于 http 协议 Web 服务器,而 Netty 通过编程自定义各种 协议,因为 Netty 本身自己能编码/解码字节流,所有 Netty 可以实现,HTTP 服务 FTP 服务器、UDP 服务器、RPC 器、WebSocket 服务器Redis  Proxy 服务 器、MySQL  Proxy 服务器等等。 

15Netty 发送消息有几种方式? 

Netty 有两种发送消息的方式: 

  直接写入 Channel ,消息从 ChannelPipeline 当中尾部开始 

  写入和 ChannelHandler 绑定的 ChannelHandlerContext 中,息从 ChannelPipeline  中的下一个 ChannelHandler 中移动 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老歪不歪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值