前言

大家好,我是田螺

nettynetty32
  • 公众号捡田螺的小男孩 (有田螺精心准备的面试PDF)
  • github地址,感谢每颗star:github

1. Netty是什么,它的主要特点是什么?

NettyNIOAPI

https://www.swvq.com

IT社区

NettyI/ONettyAPIWebNetty

2. Netty 应用场景了解么?

Netty
RPC、HTTP、WebSocketKafka、ActiveMQ

阿里分布式服务框架 Dubbo, 消息中间件RocketMQ都是使用 Netty 作为通讯的基础。

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

Netty的核心组件包括以下几个部分:

Java NIOSocketChannelI/ONettyI/OEventLoopEventLoopChannelI/OChannelI/ONIOChannelHandlerChannelHandlerChannelI/O NettyByteBufChannelPipelineNettyChannelPipeline

这些核心组件共同构成了Netty的核心架构,可以帮助开发人员快速地实现高性能、高并发的网络应用程序。

学新通

4. Netty的线程模型是怎样的?如何优化性能?

NettyReactorNettyEventLoopEventLoop
NettyEventLoopGroup

在实际使用中,还可以通过优化网络协议、数据结构、业务逻辑等方面来提高Netty的性能。例如,可以使用零拷贝技术避免数据拷贝,使用内存池减少内存分配和回收的开销,避免使用阻塞IO和同步操作等,从而提高应用的吞吐量和性能表现。

5. EventloopGroup了解么?和 EventLoop 啥关系?

EventLoopGroupEventLoopNetty
EventLoopGroupEventLoopI/O Netty I/OEventLoopGroup
EventLoop Netty I/OChannelI/OEventLoop Channel ChannelEventLoop 
Netty EventLoopGroupEventLoopGroup EventLoop I/O

6. Netty 的零拷贝了解么?

(Zero Copy)CPU
Netty Direct Memory  FileChannelChannelNettysendfile writevChannelNetty

IT社区

NettyCPU 

7. Netty 长连接、心跳机制了解么?

在网络编程中,长连接是指客户端与服务器之间建立的连接可以保持一段时间,以便在需要时可以快速地进行数据交换。与短连接相比,长连接可以避免频繁建立和关闭连接的开销,从而提高数据传输的效率和性能。

Channelkeepalive keepalive
keepaliveNetty Netty IdleStateHandlerIdleStateHandler 

通过使用长连接和心跳机制,可以保证客户端与服务器之间的连接处于正常的状态,从而提高数据传输的效率和性能。特别是在处理大量数据传输的场景中,长连接和心跳机制可以降低建立和关闭连接的开销,减少网络负载,提高系统的稳定性。

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

Netty NIO

编程社区

EventLoopGroupEventLoopGroupNettyNetty EventLoopGroupEventLoopEventLoopEventLoopGroup ServerBootstrap BootstrapServerBootstrap 和 Bootstrap NettyServerBootstrapBootstrap EventLoopGroupChannelChannelNettyChannel ChannelHandler。ChannelHandlerNettyChannelHandler Channel  Channel
NettyNetty

学新通

9. Netty 的 Channel 和 EventLoop 之间的关系是什么?

NettyChannelEventLoopChannel
ChannelEventLoopEventLoopChannelChannelEventLoopEventLoop

https://www.swvq.com

EventLoopChannelChannelChannelEventLoop

学新通

10. 什么是 Netty 的 ChannelPipeline,它是如何工作的?

NettyChannelChannelPipelineChannelChannelPipelineHandler
ChannelPipelineInboundHandlerChannelHandlerContext.fireXXX()Channel
ChannelPipeline

编程社区

InboundChannelChannelPipelineInboundHandlerInboundHandlerOutboundChannelChannelPipelineOutboundHandlerOutboundHandlerChannelHandlerContextChannelPipelineChannelHandlerChannelHandlerContextChannelPipelineChannel、ChannelPipeline和其他ChannelHandler

通过使用ChannelPipeline,Netty实现了高度可配置和可扩展的网络通信模型,使得开发人员可以根据自己的需求选择和组合不同的处理器,以构建出高效、稳定、安全的网络通信系统。

11. Netty 中的 ByteBuf 是什么,它和 Java 的 ByteBuffer 有什么区别?

Netty ByteBufAPIByteBuf Java NIOByteBuffer

学新通

ByteBufByteBufferByteBuf ByteBuf ByteBuf
ByteBuf buffer = Unpooled.buffer(10);
buffer.writeBytes("hello".getBytes());

while (buffer.isReadable()) {
  System.out.print((char) buffer.readByte());
}
Unpooled.buffer()ByteBufbufferwriteBytes()"hello" isReadable() readByte()

12. Netty 中的 ChannelHandlerContext 是什么,它的作用是什么?

NettyChannelHandlerContextChannelPipelineHandlerNetty的IOChannelHandlerContextI/OChannelPipelineChannelPipeline
ChannelPipelineHandlerNettyChannelHandlerContextHandlerHandlerChannelPipelineChannelI/ONettyI/OChannelHandlerContextHandler

编程社区

ChannelHandlerContextNettyHandler

13. 什么是 Netty 的 ChannelFuture,它的作用是什么?

NettyChannelFutureI/OChannelFuture
ChannelFutureNettyChannelFutureChannelFutureListenerChannelFutureListener

学新通

ChannelFuture
ChannelFutureNettyI/OI/O

编程社区

14. Netty 中的 ChannelHandler 是什么,它的作用是什么?

NettyChannelHandler
channelRead(ChannelHandlerContext ctx, Object msg)channelReadComplete(ChannelHandlerContext ctx)exceptionCaught(ChannelHandlerContext ctx, Throwable cause)channelActive(ChannelHandlerContext ctx)channelInactive(ChannelHandlerContext ctx)
ChannelHandlerChannelPipelineChannelPipelineChannelHandlerChannelChannelPipelineChannelHandler
ChannelHandler

学新通

15. Netty 中的各种 Codec 是什么,它们的作用是什么?

NettyCodec JavaJavaJava
Codec

https://www.swvq.com

ByteToMessageCodecJava  JavaMessageToByteEncoderJavaByteToMessageDecoder JavaStringEncoder 和 StringDecoderLengthFieldPrepender 和 LengthFieldBasedFrameDecoderTCPObjectDecoder和ObjectEncoderJavaJava
Codec 

16. 什么是 Netty 的 BootStrap,它的作用是什么?

Netty的BootstrapNetty

编程社区

BootstrapChannelPipelinehandlerBootstrap
NettyBootstrap
NettyBootstrapNettyNettyBootstrapNetty

17.Netty的IO模型是什么?与传统的BIO和NIO有什么不同?

NettyIONIO(Non-blocking IO)BIO(Blocking IO)NIO
NIONettyNIO
NettyReactorIOHandlerNettyHandlerIOIONettyChannelChannelNIO、EPoll、OIO

18. 如何在Netty中实现TCP粘包/拆包的处理?

TCPTCP

https://www.swvq.com

IT社区

100
// 编码器,将消息的长度固定为100字节
pipeline.addLast("frameEncoder", new LengthFieldPrepender(2));
pipeline.addLast("messageEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 解码器,根据固定长度对消息进行拆分
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(100, 0, 2, 0, 2));
pipeline.addLast("messageDecoder", new StringDecoder(CharsetUtil.UTF_8));
\r\n
// 编码器,以"\r\n"作为消息分隔符
pipeline.addLast("frameEncoder", new DelimiterBasedFrameEncoder("\r\n"));
pipeline.addLast("messageEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 解码器,根据"\r\n"对消息进行拆分
pipeline.addLast("frameDecoder", new DelimiterBasedFrameDecoder(1024, Delimiters.lineDelimiter()));
pipeline.addLast("messageDecoder", new StringDecoder(CharsetUtil.UTF_8));
  • 消息头部加长度字段:在消息的头部加上表示消息长度的字段,在发送端发送消息时先发送消息长度,再发送消息内容。在接收端,先读取消息头部的长度字段,再根据长度读取消息内容。
// 编码器,将消息的长度加入消息头部
pipeline.addLast("frameEncoder", new LengthFieldPrepender(2));
pipeline.addLast("messageEncoder", new StringEncoder(CharsetUtil.UTF_8));
// 解码器,先读取消息头部的长度字段,再根据长度读取消息内容
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(1024, 0, 2, 0, 2));
pipeline.addLast("messageDecoder", new StringDecoder(CharsetUtil.UTF_8));

19. Netty如何处理大文件的传输?

NettyChunkedWriteHandlerChunkedWriteHandlerChunkChunkedData

具体使用方法如下:

学新通

ChannelPipelineChunkedWriteHandler
pipeline.addLast(new ChunkedWriteHandler());
ChunkedData
public class MyServerHandler extends SimpleChannelInboundHandler<Object> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            // 处理HTTP请求
            // ...
        } else if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;
            // 处理HTTP内容
            if (content instanceof LastHttpContent) {
                // 处理完整个HTTP请求
                // ...
            } else if (content instanceof HttpChunkedInput) {
                HttpChunkedInput chunkedInput = (HttpChunkedInput) content;
                // 处理ChunkedData
                while (true) {
                    HttpContent chunk = chunkedInput.readChunk(ctx.alloc());
                    if (chunk == null) {
                        break;
                    }
                    // 处理单个Chunk
                    // ...
                }
            }
        }
    }
}
ChunkedFile
public void sendFile(Channel channel, File file) throws Exception {
    RandomAccessFile raf = new RandomAccessFile(file, "r");
    DefaultFileRegion fileRegion = new DefaultFileRegion(raf.getChannel(), 0, raf.length());
    HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/");
    HttpUtil.setContentLength(request, raf.length());
    channel.write(request);
    channel.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, file.length(), 8192)));
}

在传输大文件时,还需要注意以下几点

ChunkedFileChunk8KBChannelPipelineWriteBufferWaterMark
pipeline.addLast(new WriteBufferWaterMark(8 * 1024, 32 * 1024));

20. 如何使用Netty实现心跳机制?

Netty

编程社区

以下是使用Netty实现心跳机制的基本步骤

学新通

  • 定义心跳消息的类型。
public class HeartbeatMessage implements Serializable {
    // ...
}
ChannelPipelineIdleStateHandler
pipeline.addLast(new IdleStateHandler(0, 0, 60, TimeUnit.SECONDS));
userEventTriggered
public class MyServerHandler extends SimpleChannelInboundHandler<Object> {
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                // 读空闲,发送心跳包
                ctx.writeAndFlush(new HeartbeatMessage());
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
channelRead
public class MyClientHandler extends SimpleChannelInboundHandler<Object> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HeartbeatMessage) {
            // 收到心跳包,不做处理
            return;
        }
        // 处理其他消息
        // ...
    }
}
Unpooled.EMPTY_BUFFER

21. Netty中如何实现SSL/TLS加密传输?

NettySSL/TLS  SSLHandlerSSLHandler ChannelPipelinehandler
 SSL/TLS

IT社区

// 创建 SSLContext 对象,用于构建 SSLEngine
SSLContext sslContext = SSLContext.getInstance("TLS");

// 初始化 SSLContext
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("server.jks"), "password".toCharArray());
keyManagerFactory.init(keyStore, "password".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

// 获取 SSLEngine
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setUseClientMode(false);

// 添加 SslHandler 到 ChannelPipeline 中
pipeline.addLast("ssl", new SslHandler(sslEngine));

22. NioEventLoopGroup 默认的构造函数会起多少线程?

NioEventLoopGroupavailableProcessors()
NioEventLoopGroupnThreads  0Runtime.getRuntime().availableProcessors()

IT社区

NioEventLoopGroup NioEventLoopGroup

23. 如何使用Netty实现WebSocket协议?

NettyWebSocketWebSocketServerProtocolHandler WebSocketServerProtocolHandler  ChannelHandler HTTPWebSocket WebSocket
WebSocket

编程社区

// 添加 HTTP 请求解码器
pipeline.addLast("httpDecoder", new HttpRequestDecoder());
// 添加 HTTP 响应编码器
pipeline.addLast("httpEncoder", new HttpResponseEncoder());
// 添加 HTTP 聚合器
pipeline.addLast("httpAggregator", new HttpObjectAggregator(65536));
// 添加 WebSocket 服务器协议处理器
pipeline.addLast("webSocketHandler", new WebSocketServerProtocolHandler("/ws"));
// 添加自定义的 WebSocket 处理器
pipeline.addLast("handler", new MyWebSocketHandler());

WebSocketServerProtocolHandler  WebSocketURLMyWebSocketHandler WebSocket

https://www.swvq.com

24. Netty 高性能表现在哪些方面?

I/ONetty NIOI/O NettyNetty Reactor I/ONettyByteBufNetty ChannelHandler

25. Netty 和 Tomcat 的区别?

Netty 和 TomcatJava Web 
Tomcat BIO(Blocking I/O)Netty NIO(Non-Blocking I/O)TomcatNetty EventLoop EventLoop EventLoopTomcat HTTP 和 HTTPS Netty HTTP 和 HTTPSTCP、UDP 和 WebSocketTomcatNetty Tomcat Web MVCWebNetty 

26. 服务端Netty的工作架构图

             ┌───────┐        ┌───────┐
             │ Channel │◀───────│ Socket│
             │Pipeline │        │       │
             └───────┘        └───────┘
                   ▲                 │
                   │                 │
         ┌─────────┴─────────┐       │
         │                   │       │
         ▼                   ▼       ▼
┌──────────────┐   ┌──────────────┐  ┌──────────────┐
│EventLoopGroup│   │EventLoopGroup│  │EventLoopGroup│
│       boss   │   │     work     │  │     work     │
└──────────────┘   └──────────────┘  └──────────────┘
         ▲                   ▲       ▲
         │                   │       │
┌────────┴─────────┐ ┌────────┴─────────┐
│     NioServerSocketChannel   │   NioSocketChannel      │ ...
└──────────────────┘ └──────────────────┘

整个服务端 Netty 的工作架构图包括了以下几个部分:

编程社区

Socket EventLoop
EventLoopGroupEventLoopGroup bossworkEventLoopwork EventLoopEventLoop NioSocketChannel

27. 简单聊聊:Netty的线程模型的三种使用方式?

Netty的线程模型有三种使用方式,分别是单线程模型、多线程模型和主从多线程模型。

IT社区

I/OI/OI/OI/OI/OI/ONIOI/OI/O

28. Netty 是如何保持长连接的

https://www.swvq.com

NettyIdleStateHandlerNettyChannelFutureListenerChannelFutureHTTP/1.1TCPNettyHttpClientCodec和HttpObjectAggregatorHTTP/1.1WebSocketTCPNettyWebSocketServerProtocolHandlerWebSocketClientProtocolHandlerWebSocket

29. Netty 发送消息有几种方式?

Netty

学新通

Channel Channelflush()ChannelHandlerContext Channel.write(Object msg)ChannelHandlerContext.write(Object msg)ChannelHandlerContextflush()  ChannelHandlerContextChannelHandlerContext.write(Object msg) ChannelHandlerContext.flush()
Netty ChannelFuture

30. Netty 支持哪些心跳类型设置?

Netty

https://www.swvq.com

NettyChannelInboundHandler ChannelInboundHandler

需要注意的是,为了避免因心跳机制导致的网络负载过大或者频繁的连接断开和重连,应该根据具体业务场景选择适合的心跳类型和频率。

31. Netty的内存管理机制是什么?

NettyByteBuf ByteBufNettyJDKByteBuffer 
Netty ByteBuf

https://www.swvq.com

ByteBufJVMXMLByteBuf
NettyJVM 
ByteBuf Netty

https://www.swvq.com

32. Netty 中如何实现高可用和负载均衡?

Netty

编程社区

Nginx、HAProxyNettyEventLoopEventLoopZookeeper、Consul

本篇文章来至:IT社区