netty的⾯试题
webgis开发实例教程1,netty 是什么?
netty是⼀款基于NIO(⾮阻塞IO)的通信框架,对于BIO(阻塞IO)来说,很⼤的提⾼了其并发性。极⼤的简化并优化了tcp和udp套接字服务器等⽹络编程,并且性能和安全性更好,⽀持多种协议,如ftp,smtp,http等
BIO可参考java jdk中的 ServerSocket的写法,在读取字节流时,没有可⽤于前后移动的索引,只是⼀个连续的数据流,每次客户端请求链接到服务器,它都会阻塞⼀个线程,如果需要很多同时链接,就需要⼀个线程池。
NIO是基于套接字连接的⾮阻塞API,也就意味着对可⽤线程的数量并不紧密,使⽤它,⼀个线程可以同时处理多个连接。⽐如netty的channel。
2,netty的特点是什么?为什么要⽤netty?
⾼并发:⽐java api有更好的吞吐量,较低的延时,减少内存拷贝,资源耗时更少(这个得益于共享池和重⽤)
传输快: Netty 的传输依赖于零拷贝特性,尽量减少不必要的内存拷贝,实现了更⾼效率的传输。borderstyle设置边框样式的属性有哪些
易⽤性:设置了多种编解码功能,⽀持多种主流协议。扩展性强,⽽且稳定。
netty⽐jdk⾃带的NIO相关的API更加易⽤。
简单⽽强⼤的线程模型
⾃带编解码解决TCP粘包/拆包问题
⾃带各种协议栈
真正的⽆连接数据包套接字⽀持
⽐直接使⽤jdk的api有更⾼的吞吐量,更低的延时,更低的资源和更少的内存复制
安全性强,有完整的SSL/TLS以及StartTLS⽀持
成熟稳定,现在很多开源项⽬使⽤了netty,⽐如dubbo和es等
3,什么是netty的零拷贝?
netty的接受和发送byteBuffer 采⽤ direct buffers,使⽤堆外直接内存进⾏Socket读写,不需要进⾏字
节缓冲区的⼆次拷贝,如果使⽤传统的堆内存进⾏socket读写,jvm会将堆内存buffer拷贝⼀份到直接内存中,然后才写⼊socket中,相对于堆外直接内存,消息在发送过程中多了⼀次缓存区的内存拷贝。
netty提供了组合Buffer对象,可以聚合多个byteBuffer对象,⽤户可以像操作⼀个Buffer那样⽅便的对组合Buffer进⾏操作,避免了传统通过内存拷贝的⽅式将⼏个buffer合并成⼀个⼤的buffer。
netty的⽂件传输采⽤了transferTo⽅法,它可以直接将⽂件的缓冲区的数据发送到⽬标Channel,避免了传统通过循环write的⽅法导致的内存拷贝问题。
4,netty的使⽤场景?
dubbo框架就是基于netty的通信组件,还有ElasticSearch 也是。由Transport负责通信,基于tcp通信采⽤netty实现。RocketMQ,gRPC 等
作为RPC框架的⽹络通信⼯具:我们在分布式系统中,不通服务节点之间经常需要相互调⽤,这个时候就需要RPC框架了,就可以⽤netty实现,⽐如我调⽤另外⼀个节点的⽅法的化,⾄少需要让对⽅知道我调⽤的是哪个类中的哪个⽅法以及相关参数
实现⼀个即时通讯系统: 类似与
实现消息推送系统:
5,netty⾼性能的具体表现?
同步⾮阻塞IO,
fopen的原型函数为内存零拷贝,
内存池设计,申请的内存可以重⽤,主要指直接内存,内部实现是⼀颗⼆叉树树管理内存分配情况,
串形化处理读写:避免使⽤锁带来的性能开销
⾼性能序列化协议: ⽀持protobuf等⾼性能序列化协议。
6,netty和tomcat的区别?
作⽤不同:tomcat是Servlet容器,可以视为web服务器,⽽netty是异步事件驱动的⽹络应⽤程序框架和⼯具⽤于简化⽹络编程。
协议不同:tomcat是基于http协议的web服务器,⽽netty是通过编程⾃定义各种协议,因为netty本⾝
⾃⼰能编码/解码字节流,所有netty可以实现,http服务,ftp服务,udp服务,rpc服务,websocket服务,redis的proxy服务,mysql的proxy服务等
7,netty中有哪些重要的组件?
Channel:netty⽹络操作抽象类。它包括了基本的 I/O 操作,如 bind、connect、read、write 等。⽐较常⽤的Channel接⼝实现类是NioServerSocketChannel(服务端)和NioSocketChannel(客户端),这两个 Channel 可以和 BIO 编程模型中的
ServerSocket以及Socket两个概念对应上。Netty 的 Channel 接⼝所提供的 API,⼤⼤地降低了直接使⽤ Socket 类的复杂性。
EventLoop:主要是配合 Channel 处理 I/O 操作,⽤来处理连接的⽣命周期中所发⽣的事情。主要作⽤实际就是负责监听⽹络事件并调⽤事件处理器进⾏相关 I/O 操作的处理。Channel 为 Netty ⽹络操作(读写等操作)抽象类,EventLoop 负责处理注册到其上的Channel 处理 I/O 操作,两者配合参与 I/O 操作。
ChannelFuture:Netty 框架中所有的 I/O 操作都为异步的,因此我们需要 ChannelFuture 的 addListener()注册⼀个
ChannelFutureListener 监听事件,当操作执⾏成功或者失败时,监听就会⾃动触发返回结果。
ChannelHandler:充当了所有处理⼊站和出站数据的逻辑容器。ChannelHandler 主要⽤来处理各种事件,这⾥的事件很⼴泛,⽐如可以是连接、数据接收、异常、数据转换等。
ChannelPipeline:为 ChannelHandler 链提供了容器,当 channel 创建时,就会被⾃动分配到它专属的 ChannelPipeline,这个关联是永久性的。
8,Netty 发送消息有⼏种⽅式?
直接写⼊ Channel 中,消息从 ChannelPipeline 当中尾部开始移动;
写⼊和 ChannelHandler 绑定的 ChannelHandlerContext 中,消息从 ChannelPipeline 中的下⼀个 ChannelHandler 中移动。
9,默认情况 Netty 起多少线程?何时启动?
Netty 默认是 CPU 处理器数的两倍,
// 从1,系统属性,CPU核⼼数*2 这三个值中取出⼀个最⼤的 //可以得出 DEFAULT_EVENT_LOOP_THREADS 的值为CPU核⼼数*2
mysql面试题常问private static final int DEFAULT_EVENT_LOOP_THREADS = Math.max(1,
bind 完之后启动。
channelFuture = serverBootstrap.bind(PORT).sync()
10,什么是TCP粘包/拆包?有什么解决⽅法?
TCP粘包/拆包是基于TCP发送数据的时候,出现了多个字符串“粘”在了⼀起或者⼀个字符串被“拆”开的问题,
解决⽅案:
使⽤netty⾃带的解码器:
LineBasedFrameDecoder : 发送端发送数据包的时候,每个数据包之间以换⾏符作为分隔,LineBasedFrameDecoder 的⼯作原理是它依次遍历 ByteBuf 中的可读字节,判断是否有换⾏符,然后进⾏相应的截取。
DelimiterBasedFrameDecoder : 可以⾃定义分隔符解码器,LineBasedFrameDecoder 实际上是⼀种特殊的
DelimiterBasedFrameDecoder 解码器。
FixedLengthFrameDecoder: 固定长度解码器,它能够按照指定的长度对消息进⾏相应的拆包。
LengthFieldBasedFrameDecoder
matlab激活文件在哪里⾃定义序列化编解码器:
在 Java 中⾃带的有实现 Serializable 接⼝来实现序列化,但由于它性能、安全性等原因⼀般情况下是不会被使⽤到的。
通常情况下,我们使⽤ Protostuff、Hessian2、json 序列⽅式⽐较多,另外还有⼀些序列化性能⾮常好的序列化⽅式也是很好的选择:
专门针对 Java 语⾔的:Kryo,FST 等等
跨语⾔的:Protostuff(基于 protobuf 发展⽽来),ProtoBuf,Thrift,Avro,MsgPack 等等
11,TCP长连接和短连接
我们知道 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 。
readerIdleTime:为读超时时间(即测试端⼀定时间内未接受到被测试端消息)。IdleState.READER_IDLE
writerIdleTime:为写超时时间(即测试端⼀定时间内向被测试端发送消息)。IdleState.WRITER_IDLE
allIdleTime:所有类型的超时时间。IdleState.ALL_IDLE
//⼼跳机制 PING-PONG 交互第⼀个参数设置未读时间,第⼆个参数设置为未写时间,第三个为都未进⾏操作的时间
/
/⼀般第⼀个时间是服务器设置多长时间没有收到客户端消息的时间,第⼆个是netty客户端设置多长时间给服务器发送⼀条消息的时间.⼼跳检测主要是通过向线程任务队列中添加定时任务,判断channelRead()⽅法或write()⽅法是否调⽤空闲超时,如果超时则触发超时事件执⾏⾃定义
userEventTrigger()⽅法
ch.pipeline().addLast(new IdleStateHandler(0, 0, idleTImeSec) {
@Override
protected final void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
log.info("evt {}", evt.state());
//IdleState.READER_IDLE 读空闲超时时间设定,如果channelRead()⽅法超过readerIdleTime时间未被调⽤则会触发超时事件调⽤
userEventTrigger()⽅法;表⽰如果客户端没有在规定的时间内给你发送消息,服务端就会认为这个客户端宕掉了,关闭这个链接
/
/IdleState.WRITER_IDLE 写空闲超时时间设定 allIdleTime所有类型的空闲超时时间设定,包括读空闲和写空闲;
oracle12c教程if (evt.state() == IdleState.ALL_IDLE) {
ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE);
}
}
});
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论