Netty | 一起来了解了解Netty吧

简介: Netty | 一起来了解了解Netty吧

QQ截图20220525204137.png


本文主要讲述Netty相关概念及为什么会出现Netty,Netty的作用有哪些等?以及学习Netty需要什么。


前言:


我其实更好奇的是:你是因为什么点进了这篇博客,是想要了解Netty;或者是因为自己本心中的好奇心;亦或者是业务场景中需要用Java网络编程,然后百度搜索,搜到了Netty。


如果你想要了解,这篇文章我想是适合你的。如果你是想要满足自己的好奇心,想要深究一番的,那么这篇就是Netty的开山篇。如果是业务中需要用到Netty框架,并且已经有了好的基础,我想可以直接跳过这一篇,直接进入实战加设计理论篇可能会更好。


我想要学习Netty框架一方面是因为好奇框架中服务与服务之间的通信,一直是处于懂得使用,而不懂其然的状态;另一方面是我想掌握这个技术,想自己琢磨出点东西,写一点属于自己的东西,扩展自己的知识面,Netty正好与我不谋而合,所以我来了。


建议:学习Netty框架最好是已经对Java IO编程、网络编程、多线程编程有一定了解。

Netty 官网


一、Java网络编程


1.1、Java BIO


最早期的 Java API(java.net)只支持由本地系统套接字库提供的所谓的阻塞函数。


简单示例:


/**
 * @Author: crush
 * @Date: 2021-08-23 11:51
 * version 1.0c
 */
public class BioServer {
    public static void main(String[] args) throws Exception {
        //1、创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(8888);
        while (true) {
            //2、监听 等待客户端连接。 该方法阻塞,直到建立连接。
            final Socket socket = serverSocket.accept();
            System.out.println("连接到一个客户端");
            //3、就创建一个线程,与之通讯(单独写一个方法)
            new Thread(() -> {
                //4、可以和客户端通讯
                handler(socket);
            }).start();
        }
    }
    /**
     * 编写一个handler方法,和客户端通讯,读取客户端发过来的信息
     * @param socket
     */
    public static void handler(Socket socket) {
        try {
            byte[] bytes = new byte[1024];
            //通过socket获取输入流
            InputStream inputStream = socket.getInputStream();
            //循环的读取客户端发送的数据
            while (true) {
                //从输入流中读取一定数量的字节并将它们存储到缓冲区数组b 。
                //实际读取的字节数作为整数返回。
                //此方法会阻塞,直到输入数据可用、检测到文件结尾或抛出异常。
                int read = inputStream.read(bytes);
                if (read != -1) {
                    //处理客户端发送的数据::输出客户端发送的数据 
                    System.out.println(new String(bytes, 0, read));
                } else {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


说几个比较重要的点:


  1. ServerSocket 上的 accept()方法将会一直阻塞到一个连接建立 ,随后返回一个 新的 Socket 用于客户端和服务器之间的通信。该 ServerSocket 将继续监听传入的 连接。


  1. InputStream流处理方式.


  1. read()方式将会阻塞,直到在 处一个由换行符或者回车符结尾的字符串被 读取。


  1. 处理客户端发送的数据。


需要注意到的点


这段代码只能同时处理一个连接,如果要管理多个客户端,需要为每个Socket创建一个Thread。我们可以画出它的模型图了,如下:


QQ截图20220525204442.png


这有什影响呢?


第一、在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,会造成资源极大的浪费。


第二、Java需要为每个线程的调用栈都分配内存,其默认值大小区间为 64 KB 到 1 MB,具体取决于操作系统,超过1000的话,可能JVM的内存都会被干掉一半。


第三、即使 Java 虚拟机(JVM)在物理上可以支持非常大数量的线程,但是远在到达该极限之前,上下文切换所带来的开销就会带来麻烦。


这种模式比较适用于中小型的并发,一旦到了成千上万的话,效果就会非常不理想了,更多的话甚至就是糟糕啦。


当然Java已经发展这么多年了,不可能不突破的哈,在jdk1.4的时候就增加了Java NIO


如果还想了解一下Java BIO网络编程👈


1.2、Java NIO


Java BIO是阻塞式的调用,Java NIO 就是来解决这个问题的。Java NIO 是属于非阻塞调用,对原生的IO 也做了进一步的改写。在Jdk1.4的时候引入的,位于java.nio包下。


Java NIO的模型图是这样的:


QQ截图20220525204518.png


几个重要的点:


  1. 不再像BIO那样是一个线程对应着一个客户端,一个单一的线程便可以处理多个并发的连接,减少了内存管理和上下文切换所带来开销;


  1. 它使用了事件通知 API 以确定在一组非阻塞套接字中有哪些已经就绪能够进行 I/O 相关的操作。Selector 会根据不同的事件,在各个通道上切换,但是程序切换到哪个 Channel 是由事件(比如:连接请求、数据到达)决定的。只有当socket真正有读写事件时,才会真正调用实际的IO读写操作。


  1. 当没有 I/O 操作需要处理的时候,线程也可以被用于其他任务。


NIO是解决了BIO所产生的一些问题,但是编程也同时的变得繁琐了。


框架是什么?


个人简单理解:就是加了一层,一层不行就加两层,总之没有加层解决不了的。(😃狗头保命)


另外就是直接使用底层的API暴露了复杂性,并且不好去进行扩展,所以勒,我们就要用较简单的抽象来隐藏底层实现的复杂性啦。😁


想要了解更详细的Java NIO 网络编程可以点👈。


二、Netty简介


2.1、概述


Netty是由JBOSS提供的一个java开源框架,现为Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。


也就是说,Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。


2.2、Netty 特点


分类 Netty的特性
设计 1、统一的API,支持多种类型传输,阻塞的和非阻塞的。2、简单而强大的线程模型 3、逻辑组件支持复用,不需要重复造轮子
易于使用 详细的JavaDoc文档,有许多的示例
性能 拥有比 Java 的核心 API 更高的吞吐量以及更低的延迟,得益于池化和复用,拥有更低的资源消耗,最少的内存复制
健壮性 不会因为慢速、快速或者超载的连接而导致 OutOfMemoryError ;消除在高速网络中 NIO 应用程序常见的不公平读/写比率
安全性 完整的 SSL/TLS 以及 StartTLS 支持;可用于受限环境下,如 Applet 和 OSGI
社区 社区活跃,更新速快


2.3、异步和事件驱动


知道异步先看同步是什么吧,同步简单说就是串行。


举个例子:你去餐馆,在服务员那点了菜,然后服务员去后厨告诉厨师你点了什么菜,然后等厨师炒好,给你送过来。


异步


异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、通知和回调来通知调用者。


举个生活中的例子就是:


  1. 你去餐馆,在服务员那点了菜,服务员去后厨告诉厨师你点的菜,然后就回来告诉你菜等会上。


  1. 服务员就去做其他事情。


  1. 菜好了,服务员又给你端过来了。


Netty 中的 I/O 操作是异步的,包括 Bind、Write、Connect 等操作会简单的返回一个 ChannelFuture


调用者并不能立刻获得结果,而是通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得 IO  操作结果。


事件驱动


Netty使用了异步的事件驱动模型,来触发网络I/O的各种操作,其在socket层上面封装一层异步事件驱动模型,使得业务代码不需要关心网络底层,就可以编写异步的无网络I/O阻塞的代码。


事件发生时主线程把事件放入事件队列,在另外线程不断循环消费事件列表中的事件,调用事件对应的处理逻辑处理事件。事件驱动方式也被称为消息通知方式,其实是设计模式中观察者模式的思路。


三、自言自语


想了很久,最后还是把这一篇文章拆成两篇了,不然篇幅太长了,让人看着发愁。

下半篇是:


属于你的第一个Netty应用程序



目录
相关文章
netty
netty
64 0
|
2月前
|
设计模式 网络协议 NoSQL
netty(四)
netty(四)
|
3月前
|
网络协议 前端开发 安全
Netty
Netty
178 1
|
2月前
|
机器学习/深度学习 分布式计算 搜索推荐
Netty(一)
Netty(一)
|
5月前
|
消息中间件 编解码 Java
Netty介绍
Netty介绍
55 4
Netty介绍
|
6月前
|
存储 Java API
Netty指南
Netty指南
77 2
|
6月前
|
监控 前端开发 Java
Netty使用篇
Netty使用篇
|
安全 Java Linux
Netty4 使用总结
Netty4 使用总结
54 0
netty练习
netty练习
44 0
|
消息中间件 网络协议 Dubbo
Netty是什么,为什么要使用Netty?
最近,也不知道什么原因,经常有粉丝问我关于Netty的问题。难道是大厂面试更卷了,开始关注更加底层的框架了?先不深究什么原因了,今天,我给大家分享一下什么是Netty,它能解决什么问题?
92 0