Netty(netty和tomcat的区别)

  本篇文章为你整理了Netty(netty和tomcat的区别)的详细内容,包含有netty websocket netty和tomcat的区别 netty有必要学吗 netty线程模型 Netty,希望能帮助你了解 Netty。

  1.1 Channel Buffer

  channel 有一点类似于 stream,它就是读写数据的双向通道,可以从 channel 将数据读入 buffer,也可以将 buffer 的数据写入 channel,而之前的 stream 要么是输入,要么是输出,channel 比 stream 更为底层

  graph LR

  channel -- buffer

  buffer -- channel

  常见的 Channel 有

  FileChannel

  DatagramChannel

  SocketChannel

  ServerSocketChannel

  buffer 则用来缓冲读写数据,常见的 buffer 有

  ByteBuffer

  MappedByteBuffer

  DirectByteBuffer

  HeapByteBuffer

  
1.2 Selector

  selector 单从字面意思不好理解,需要结合服务器的设计演化来理解它的用途

  多线程版设计

  graph TD

  subgraph 多线程版

  t1(thread) -- s1(socket1)

  t2(thread) -- s2(socket2)

  t3(thread) -- s3(socket3)

  ⚠️ 多线程版缺点

  内存占用高

  线程上下文切换成本高

  只适合连接数少的场景

  线程池版设计

  graph TD

  subgraph 线程池版

  t4(thread) -- s4(socket1)

  t5(thread) -- s5(socket2)

  t4(thread) -.- s6(socket3)

  t5(thread) -.- s7(socket4)

  ⚠️ 线程池版缺点

  阻塞模式下,线程仅能处理一个 socket 连接

  仅适合短连接场景

  selector 版设计

  selector 的作用就是配合一个线程来管理多个 channel,获取这些 channel 上发生的事件,这些 channel 工作在非阻塞模式下,不会让线程吊死在一个 channel 上。适合连接数特别多,但流量低的场景(low traffic)

  graph TD

  subgraph selector 版

  thread -- selector

  selector -- c1(channel)

  selector -- c2(channel)

  selector -- c3(channel)

  调用 selector 的 select() 会阻塞直到 channel 发生了读写就绪事件,这些事件发生,select 方法就会返回这些事件交给 thread 来处理

  2. ByteBuffer

  有一普通文本文件 data.txt,内容为

  

1234567890abcd

 

  

 

  使用 FileChannel 来读取文件内容

  

@Slf4j

 

  public class ChannelDemo1 {

   public static void main(String[] args) {

   try (RandomAccessFile file = new RandomAccessFile("helloword/data.txt", "rw")) {

   FileChannel channel = file.getChannel();

   ByteBuffer buffer = ByteBuffer.allocate(10);

   do {

   // 向 buffer 写入

   int len = channel.read(buffer);

   log.debug("读到字节数:{}", len);

   if (len == -1) {

   break;

   // 切换 buffer 读模式

   buffer.flip();

   while(buffer.hasRemaining()) {

   log.debug("{}", (char)buffer.get());

   // 切换 buffer 写模式

   buffer.clear();

   } while (true);

   } catch (IOException e) {

   e.printStackTrace();

  

 

  输出

  

10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 读到字节数:10

 

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 1

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 2

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 3

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 4

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 5

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 6

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 7

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 8

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 9

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 0

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 读到字节数:4

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - a

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - b

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - c

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - d

  10:39:03 [DEBUG] [main] c.i.n.ChannelDemo1 - 读到字节数:-1

  

 

  2.1 ByteBuffer 正确使用姿势

  向 buffer 写入数据,例如调用 channel.read(buffer)

  调用 flip() 切换至读模式

  从 buffer 读取数据,例如调用 buffer.get()

  调用 clear() 或 compact() 切换至写模式

  重复 1~4 步骤

  2.2 ByteBuffer 结构

  ByteBuffer 有以下重要属性

  capacity

  position

  limit

  一开始

  写模式下,position 是写入位置,limit 等于容量,下图表示写入了 4 个字节后的状态

  flip 动作发生后,position 切换为读取位置,limit 切换为读取限制

  读取 4 个字节后,状态

  clear 动作发生后,状态

  compact 方法,是把未读完的部分向前压缩,然后切换至写模式

  

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: