前言
大家好,我是田螺。
nettynetty32
- 公众号:捡田螺的小男孩 (有田螺精心准备的面试PDF)
- github地址,感谢每颗star:github
1. Netty是什么,它的主要特点是什么?
NettyNIOAPIhttps://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 writevChannelNettyIT社区
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
ChannelEventLoopEventLoopChannelChannelEventLoopEventLoophttps://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
Codechttps://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粘包/拆包的处理?
TCPTCPhttps://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/TLSIT社区
// 创建 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 WebSockethttps://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 ByteBufhttps://www.swvq.com
ByteBufJVMXMLByteBuf
NettyJVM
ByteBuf Nettyhttps://www.swvq.com
32. Netty 中如何实现高可用和负载均衡?
Netty编程社区
Nginx、HAProxyNettyEventLoopEventLoopZookeeper、Consul
本篇文章来至:IT社区