zoukankan      html  css  js  c++  java
  • Netty

    Netty

    一、概述

      NIO的框架,主要是可以使系统在单线程的情况下可以同时处理多个客户端请求。主要是用了NIO的多路复用的技术

    二、技术特点

      零拷贝

      Netty使用堆外直接内存进行Socket读写,不需要进行缓冲区的二次拷贝,如果使用传统内存,JVM会将内存Buffer拷贝一份到直接内存中,然后才写入Socket中

      Netty提供了组合Buffer对象,可以聚合多个Buffer对象,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。

      Netty的文件传输蚕蛹了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题

      内存池

      为了解决堆外直接内存的分配和回收是一件耗时的操作,Netty提供了基于内存池的缓冲区重用机制

      高效的Reactor线程模型

      Reactor单线程模型,Reactor多线程模型,主从Reactor多线程模型

    Reactor单线程模型

      指所有的IO操作都在同一个NIO线程上面完成,NIO线程的职责如下

      1) 作为 NIO 服务端,接收客户端的 TCP 连接;
      2) 作为 NIO 客户端,向服务端发起 TCP 连接;
      3) 读取通信对端的请求或者应答消息;
      4) 向通信对端发送消息请求或者应答消息。
    Reactor多线程模型
      与单线程最大的区别是有一组NIO线程处理IO操作。有专门一个NIO线程用于监听服务端,接收客户端的TCP连接请求。网络IO操作-读、写等由一个NIO线程池负责。

    传统IO每个客户端对应一个服务端,每个连接创建成功后都需要一个线程来维护,每个线程包含一个while死循环

    如果并发过多,传统IO就会创建越多的线程,这是非常消耗资源的。而且是阻塞式通信,频繁的线程切换,性能下降,而且IO是以字节流为单位,效率不高。

      NIO编程

    客户端连接channel,channel注册到selector中,每个channel都有一个selectkey,buffer通过selectkey来查找对应的channel来进行读写

      所以NIO可以理解为非阻塞IO,新来一个连接,不再创建一个新的线程,而是把这条连接绑定到固定的线程,然后这条连接的所有读写都由这个线程来负责。

    IO模型中,一个连接都会常见一个线程,对应一个while死循环,死循环的目的就是不断检测这条连接上是否有数据可以读。

    NIO中可以把许多while死循环变成一个死循环,这个死循环由一个线程控制。这就是NIO模型中Selector的作用。来检测出有数据可读的连接。

    NIO三大组件

      通道、缓冲、选择器

    通道:Stream升级版,Stream是单向的,读写分离,channel是双向的可以进行读的操作,也可以进行写的操作。

    缓冲:内存区域存数据

    选择器,监控多个信道,实现多路复用的效果。

    NIO相对于IO的优势

      IO是面向流的,每次操作都是操作系统底层一个字节一个字节的读取数据,并且数据只能从一段读取到另一端,NIO是面向缓冲区的,并且可以在缓冲区中前后移动

      IO是阻塞的,当线程读取数据或者写数据时,该线程被阻塞,直到有一些数据被读取。在数据写完前,线程不能干别的事情。

      NIO是非阻塞的,不需要一直等待操作完成才能干其他事情。而是在等待的过程中可以去做别的事情。可以最大限度的使用服务器的资源

      NIO引入了IO多路复用器Selector,提供channel注册服务的线程,可以同时对接多个channel,并在线程池中为channel适配,选择合适的线程来处理channel,由于NIO模型中线程数量大大降低,线程切换效率也因此大幅度提高。

    Netty

      简单来说Netty封装了NIO,不用写一堆复杂的代码。异步事件驱动的网络应用框架。

      Netty底层IO模型可以随意切换。

      Netty自带的拆包解包,异常检测等机制,可以让使用者专心业务逻辑

      解决了空轮询的bug

      自带各种协议栈

      健壮性强大。

    使用就是导入依赖

    Netty的事件驱动

      例如很多系统会提供onClick事件,这个事件就代表鼠标按下事件。事件驱动模型:

      1、有一个事件队列

      2、鼠标按下时,往事件队列中增加一个点击事件

      3、有个时间泵,不断循环从队列取出时间,根据不同的事件,调用不同的函数。

      4、事件一般都各自保存各自的处理方法的引用。这样每个时间都能找到对应的处理方法

    为什么使用时间驱动?

      程序中的任务可以并行执行

      任务之间高度独立,彼此之间不需要互相等待

      在等待事件到来之前,任务不会阻塞

    Netty使用时间驱动的方式作为底层架构,包括:

      事件队列:接收事件的入口

      分发器:将不同的事件分发到不同的业务逻辑单元

      事件通道:分发器处理器之间的联系通道

      事件处理器:实现业务逻辑,处理完成后会发出事件,触发下一步操作

      

    Netty 功能特性:

    • 传输服务,支持 BIO 和 NIO。

    • 容器集成:支持 OSGI、JBossMC、Spring、Guice 容器。

    • 协议支持:HTTP、Protobuf、二进制、文本、WebSocket 等,支持自定义协议。

    具体实现:

      服务端:

        创建serverbootstrap来接收客户端的连接以及为已接收的连接创建子通道。

        然后创建两个线程,一个负责接收新连接,一个负责读取数据的线程

        服务端执行

        要把两个线程放进去,

        

    group就是把两个线程放进去,channel就是写一下channel对网络套接字的I/O操作,其实就是告诉这是服务端

    channelInitialize对刚创建的通道进行初始化。

    将channelHandler添加到channel的处理链路中

      组件从流水线头部进入,流水线上的工人按顺序对组件进行加工。

    流水线相当于channelpipeline

    流水线工人相当于channelHandler

    客户端:

      一样的要先创建bootstrap

      创建一个EventLoop实例,

      客户端执行

      要把group、channel、handler写一下

      客户端连接服务端

      使用while循环,用writeAndFlush发送数据。

      具体使用就是前端写这个点击事件,向这个服务端发送消息。

  • 相关阅读:
    解决Oracle XE报错ORA-12516(oracle回话数超出限制)
    端口被占用如何处理
    ORACLE initialization or shutdown in progress 错误解决办法
    oracle的闪回功能
    Linux入门
    oracle字段like多个条件
    navicat常用快捷键与SQL基本使用
    Oracle四舍五入,向上取整,向下取整
    无限循环小数化分数
    筛选素数
  • 原文地址:https://www.cnblogs.com/gushiye/p/13991213.html
Copyright © 2011-2022 走看看