Netty应用开发-之简单介绍Netty以及NIO基本开发

孙哥分布式系列课程 --- Netty应用开发


1. 引言

1.1 什么是Netty

netty.io/

Netty是一个异步事件驱动的网络应用框架。 用于快速开发可维护的高性能协议服务器和客户端。

Netty是一个NIO客户服务器框架,它能够快速和容易地开发网络应用,如协议服务器和客户端。它大大简化和精简了网络编程,如TCP和UDP套接字服务器。

快速和简单 "并不意味着开发出来的应用程序会出现可维护性或性能问题。Netty的设计是经过精心设计的,其经验来自于许多协议的实施,如FTP、SMTP、HTTP以及各种基于二进制和文本的遗留协议。因此,Netty成功地找到了一种方法来实现开发的简易性、性能、稳定性和灵活性,而没有任何妥协。

1.2 为什么要学习Netty
markdown 复制代码
1. Netty已经是行业内网络通信编程的标准,广泛应用于通信领域和很多其他中间件技术的底层。
 
2. 应用非常广泛
   1. 游戏行业
   2. 很多框架的通信底层,解决进程间通信。
      Spring WebFlux、storm、rocketMQ、dubbo等,是分布式系统,通信的核心。

2. NIO编程

markdown 复制代码
1. NIO全称成为None Blocking IO (非阻塞IO)。【JDK1.4】
2. 非阻塞 主要应用在网络通信中,能够合理利用资源,提高系统的并发效率。支持高并发的系统访问。
2.1 传统网络通信中的开发方式及问题
2.1.1 多线程版网络编程

多线程版本的网络编程:

  1. 每次处理请求都要创建一个线程
  2. 内存 占用高,不能无限制创建线程
  3. CPU使用率高
2.1.2 线程池版的网络编程
java 复制代码
//核心线程数(corePoolSize=系统cpu核数,maxinumPollSize :最多创建线程的数量
      // keepAliveTime: 最大等待时长,线程空闲时间超过这个就会销毁,
      // unit : 单位      workQueue: 队列的最大容积
      new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), 20, 120L, TimeUnit.SECONDS, 
              new ArrayBlockingQueue<Runnable>(1000));
           

缺点:客户端请求过来了,建立了连接,但它阻塞了(比如在等客户端输入键盘,)这时候就阻塞了,这使得他这个线程Thread也得等着

2.2 NIO网络通信中的非阻塞编程

服务端还是引入线程池帮我们创建线程: 核心变化:不再使用io进行通信,而是通过管道的方式 Channel NIO帮我们引入了Seletor 服务器 ,可以帮我们监控客户端的Channel是否正常通信(建立连接,没有阻塞) 有着Seletor服务器帮会我们监控,如果一个客户端处于阻塞状态,他会帮我们把他连接的线程给释放出来

3.NIO的基本开发方式

3.1 Channel简介
markdown 复制代码
1. IO通信的通道,类似于InputStream、OutputStream
2. Channel没有方向性
  • 常见Channel

    markdown 复制代码
    1. 文件操作
       FileChannel,读写文件中的数据。
    2. 网络操作
       SocketChannel,通过TCP读写网络中的数据。
       ServerSockectChannel,监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
       DatagramChannel,通过UDP读写网络中的数据。
  • 获得方式

    markdown 复制代码
    1. FileInputStreanm/FileOutputStream
    2. RandomAccessFile
    
    3. Socket
    4. ServerSocket
    5. DatagramSocket
3.2 Buffer简介
markdown 复制代码
1. Channel读取或者写入的数据,都要写到Buffer中,才可以被程序操作。
2. 因为Channel没有方向性,所以Buffer为了区分读写,引入了读模式、写模式进行区分。
  • 常见Buffer

    markdown 复制代码
    1. ByteBuffer
    2. CharBuffer
    3. DoubleBuffer
    4. FloatBuffer
    5. IntBuffer
    6. LongBuffer
    7. ShortBuffer
    8. MappedByteBuffer..
  • 获得方式

    markdown 复制代码
     1. ByteBuffer.allocate(10);
     2. encode()
3.4 第一个NIO程序分析
java 复制代码
 public class TestNIO1 {
    public static void main(String[] args) throws IOException {
        //1 创建Channel通道  FileChannel
        FileChannel channel = new FileInputStream("data.txt").getChannel();

        //2 创建缓冲区
        //1234567890
        ByteBuffer buffer = ByteBuffer.allocate(10);

        while (true) {
            //3把通道内获取的文件数据,写入缓冲区
            int read = channel.read(buffer);

            if (read == -1) break;

            //4.程序读取buffer内容,后续的操作。设置buffer为读模式。
            buffer.flip();

            //5.循环读取缓冲区中的数据
            while (buffer.hasRemaining()) {
                byte b = buffer.get();
                System.out.println("(char)b = " + (char) b);
            }

            //6. 设置buffer的写模式
            buffer.clear();
        }
    }
}


public class TestNIO2 {
    public static void main(String[] args) {
        //RadomAccessFile 异常处理
        FileChannel channel = null;
        try {
            channel = new RandomAccessFile("data.txt", "rw").getChannel();

            ByteBuffer buffer = ByteBuffer.allocate(10);

            while (true) {
                int read = channel.read(buffer);
                if (read == -1) break;

                buffer.flip();
                while (buffer.hasRemaining()) {
                    byte b = buffer.get();
                    System.out.println("(char) b = " + (char) b);
                }

                buffer.clear();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

public class TestNIO3 {
    public static void main(String[] args) {

        try (FileChannel channel = FileChannel.open(Paths.get("data.txt"), StandardOpenOption.READ);) {

            ByteBuffer buffer = ByteBuffer.allocate(10);
            while (true) {
                int read = channel.read(buffer);
                if (read == -1) break;

                buffer.flip();
                while (buffer.hasRemaining()) {
                    byte b = buffer.get();
                    System.out.println("(char)b = " + (char) b);
                }

                buffer.clear();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    } 
}
3.5 NIO开发的步骤总结
markdown 复制代码
1. 获取Channel 
2. 创建Buffer
3. 循环的从Channel中获取数据,读入到Buffer中。进行操作.
    channel.read(buffer);

    buffer.flip();//设置读模式
    循环从buffer中获取数据。
    buffer.get();
    buffer.clear();//设置写模式
相关推荐
Json____5 分钟前
学法减分交管12123模拟练习小程序源码前端和后端和搭建教程
前端·后端·学习·小程序·uni-app·学法减分·驾考题库
monkey_meng25 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
落落落sss33 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
大鲤余1 小时前
Rust,删除cargo安装的可执行文件
开发语言·后端·rust
她说彩礼65万1 小时前
Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
后端·asp.net·mvc
陈随易1 小时前
农村程序员-关于小孩教育的思考
前端·后端·程序员
_江南一点雨1 小时前
SpringBoot 3.3.5 试用CRaC,启动速度提升3到10倍
java·spring boot·后端
转转技术团队1 小时前
空间换时间-将查询数据性能提升100倍的计数系统实践
java·后端·架构
r0ad2 小时前
SpringCloud2023实战之接口服务测试工具SpringBootTest
spring boot·后端·spring cloud
酸奶代码2 小时前
Spring AOP技术
java·后端·spring