Netty

作者: 请叫我平爷 | 来源:发表于2022-02-18 08:52 被阅读0次

Netty组件

  • I/O:流的处理(输入输出)
  • Channel:通道,代表一个请求,每个Client都对应一个Channel
  • ChannelHandler:用于处理业务请求
  • ChannelHandlerContext:用于传输业务数据
  • ChannelPipeline:责任链,每个Channel都有有且仅有一个ChannelPipeline,里面有各种Handler,用于保存处理过程需要用到的ChannelHandler和ChannelHandlerContext。
  • handler:处理入站消息以及相应的事件
  • EventLoopGroup:I/O线程池,处理对应Channel对应的I/O事件
  • ServerBootstrap:服务器端启动辅助对象
  • Bootstrap:客户端启动辅助对象
  • ChannelInitalizer:Channel初始化器
  • ChannelFuture:I/O操作的执行结果,通过事件机制,获得机制结果,通过添加监听器,执行我们想要的操作
  • ByteBuf:字节序列,通过ByteBuf操作基础的字节数组和缓冲区,使用方便
    • Heap Buffer 堆缓冲区:最常用
    • Direct Buffer 直接缓冲区:内存分配不在堆,
    • Composite Buffer 复合缓冲区:

引入Netty包

<dependency> 
    <groupId>io.netty</groupId> 
    <artifactId>netty-all</artifactId> 
    <version>4.1.73.Final</version> 
</dependency> 
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>1.2.70</version> 
</dependency>

Netty写一个Server服务器

NettyHttpServer

public class NettyHttpServer { 
  private int port; 
  public NettyHttpServer(int port) { 
      this.port = port; 
  } 
  public void run() throws Exception { 
  //处理I/O操作多线程事件循环器,boss收到连接,分配到worker上 
      EventLoopGroup bossGroup = new NioEventLoopGroup(); 
      EventLoopGroup workerGroup = new NioEventLoopGroup(); 
      try { 
          ServerBootstrap b = new ServerBootstrap();//启动NIO服务的辅助启动类,用于服务通道的一系列配置 
          b.group(bossGroup, workerGroup)//绑定两个线程组 
            .channel(NioServerSocketChannel.class) // 制定NIO模式 
            .childHandler(new ChannelInitializer<SocketChannel>() { 
                      @Override protected void initChannel(SocketChannel socketChannel) throws Exception {
                                 ChannelPipeline pipeline = socketChannel.pipeline(); 
                                 pipeline.addLast(new HttpServerCodec());// http 编解码 
                                 pipeline.addLast("httpAggregator",new HttpObjectAggregator(512*1024)); // http 消息聚合器 512*1024为接收的最大contentlength 
                                 pipeline.addLast(new NettyHttpServerHandler());// 请求处理器 
                      } }); 
           ChannelFuture f = b.bind(port).sync(); // 绑定端口 
           f.channel().closeFuture().sync(); 
        } 
        finally { 
                workerGroup.shutdownGracefully(); 
                bossGroup.shutdownGracefully(); 
        } 
  } 
  public static void main(String[] args) throws Exception { 
      new NettyHttpServer(8080).run(); 
  } 
}

handler

public class NettyHttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { 
      @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception { 
          // 获取请求的uri 
          String uri = fullHttpRequest.uri(); 
          Map<String,String> resMap = new HashMap<>(); 
          resMap.put("method",fullHttpRequest.method().name()); 
          resMap.put("uri",uri); String msg = JSON.toJSONString(resMap); 
          System.out.println("resMap:"+JSON.toJSONString(fullHttpRequest)); 
          // 创建http响应 FullHttpResponse    
          response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8)); 
          // 设置头信息 
          response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8"); 
          // 将html write到客户端 
          channelHandlerContext.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE); 
    }
}

访问
http://localhost:8080/getName?name=123

优点:

  1. 并发高:
    基于NIO,当一个Socket建立好连接后,Thread并将请求交给Selector,Selector不断遍历所有的Socket,一旦Socket建立完成,会通知Thread,然后Thread处理完再返回客户端,这个是过程不阻塞的,一个Thread可以处理更多的请求。

  2. 传输快:

  • 零拷贝,再堆内存之外开辟一块内存,数据直接从IO读到那块内存中去,netty通过ByteBuf直接对这些数据进行操作,从而加快传输速度
  • 封装好:
  • 代码量少

粘包/拆包

  • TCP粘包、拆包问题:

    • TCP是一个流协议,没有分界线
    • TCP并不知道上层业务数据的具体含义,根据TCP缓冲区的具体情况进行包的划分,在业务上一个完整的包可能会被TCP分成多个包进行发送,也可能把多个小包封装成一个大的数据包发送出去,这就是所谓的粘包/拆包问题
  • 解决:

    1. 消息定长:例如每个报文大小固定200字节,不够空格补
    2. 尾部加特殊字符,如回车
    3. 将消息分为消息头和消息体,消息头中包含消息总长度字段
  • Netty解决方法:

    1. 分隔符:DelimiterBasedFrameDecoder
    2. 定长:FixedLengthFrameDecoder

相关文章

网友评论

      本文标题:Netty

      本文链接:https://www.haomeiwen.com/subject/fnjslrtx.html