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();//设置写模式
相关推荐
哎呦没21 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch39 分钟前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries3 小时前
读《show your work》的一点感悟
后端
A尘埃3 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23073 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code3 小时前
(Django)初步使用
后端·python·django
代码之光_19803 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端
编程老船长3 小时前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
IT果果日记4 小时前
DataX+Crontab实现多任务顺序定时同步
后端