在线制作论坛网站,网站制作网站做网,淘宝客网站搭建,六年级下册数学优化设计答案文章目录 1. 概述1.1 Netty 是什么#xff1f;1.2 Netty 的特点1.3 Netty 的作者1.4 Netty 的地位1.5 Netty 的优势1.6 Netty 的工作原理1.7 Netty 的应用场景1.8 Netty 的重要组件 2. 第一个程序2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理#x1f4a1; 提示 1. 概述
1.1 … 文章目录 1. 概述1.1 Netty 是什么1.2 Netty 的特点1.3 Netty 的作者1.4 Netty 的地位1.5 Netty 的优势1.6 Netty 的工作原理1.7 Netty 的应用场景1.8 Netty 的重要组件 2. 第一个程序2.1 目标2.2 服务器端2.3 客户端2.4 流程梳理 提示 1. 概述
1.1 Netty 是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers clients. Netty 是一个异步的、基于事件驱动的网络应用框架用于快速开发可维护、高性能的网络服务器和客户端。 Netty 提供了一套简洁的 API 来帮助开发者处理各种网络通信任务支持多种传输协议包括 TCP、UDP、文件传输等并且能够很好地适配各种操作系统。
1.2 Netty 的特点
异步非阻塞Netty 使用异步非阻塞 I/O 模型可以处理大量的并发连接非常适合构建高性能的服务器和客户端应用程序。高度模块化Netty 的架构设计非常灵活采用了责任链模式ChannelPipeline来处理入站和出站的数据流使得开发者可以轻松地添加自己的处理逻辑。事件驱动Netty 通过 EventLoop 来处理 I/O 事件可以高效地处理大量的并发连接。高并发Netty 能够高效地处理成千上万的并发连接非常适合构建大规模的分布式系统。跨平台Netty 支持多种操作系统并且能够根据不同的操作系统选择最佳的 I/O 模型例如在 Linux 系统上可以使用更高效的 Epoll 模型。广泛的协议支持Netty 支持多种协议包括 HTTP、WebSocket、SMTP、FTP、Mysql 等并且提供了丰富的编解码工具。易于扩展Netty 的设计考虑到了可扩展性开发者可以根据需要轻松地扩展框架的功能。
1.3 Netty 的作者 他还是另一个著名网络应用框架 Mina 的重要贡献者
1.4 Netty 的地位
Netty 在 Java 网络应用框架中的地位就好比Spring 框架在 JavaEE 开发中的地位 以下的框架都使用了 Netty因为它们有网络通信需求
Cassandra - nosql 数据库Spark - 大数据分布式计算框架Hadoop - 大数据分布式存储框架RocketMQ - ali 开源的消息队列ElasticSearch - 搜索引擎gRPC - rpc 框架Dubbo - rpc 框架Spring 5.x - flux api 完全抛弃了 tomcat 使用 netty 作为服务器端Zookeeper - 分布式协调框架
1.5 Netty 的优势
性能Netty 的异步非阻塞 I/O 模型使其能够处理大量的并发连接非常适合高并发场景。 易用性Netty 提供了一套简洁的 API使得开发者可以快速地开发网络应用程序。 社区支持Netty 拥有一个活跃的社区提供了丰富的文档和支持。
Netty vs NIONIO工作量大bug 多 需要自己构建协议解决 TCP 传输问题如粘包、半包epoll 空轮询导致 CPU 100%对 API 进行增强使之更易用如 FastThreadLocal ThreadLocalByteBuf ByteBuffer Netty vs 其它网络应用框架 Mina 由 apache 维护将来 3.x 版本可能会有较大重构破坏 API 向下兼容性Netty 的开发迭代更迅速API 更简洁、文档更优秀久经考验16年Netty 版本 2.x 20043.x 20084.x 20135.x 已废弃没有明显的性能提升维护成本高
1.6 Netty 的工作原理
Netty 的工作原理主要包括以下几个方面
创建 Channel当启动一个 Netty 应用程序时会创建一个或多个 Channel。 如果是服务器则创建一个 ServerChannel如 NioServerSocketChannel用于监听连接如果是客户端则创建一个 ClientChannel如 NioSocketChannel用于发起连接。 注册到 EventLoop每个 Channel 都会注册到一个 EventLoop 上EventLoop 负责监听该 Channel 上的 I/O 事件。事件处理当 Channel 上有 I/O 事件发生时EventLoop 会调用 ChannelPipeline 中的 ChannelHandler 来处理这些事件。任务执行除了处理 I/O 事件之外EventLoop 还可以执行与 Channel 相关的任务如用户提交的业务逻辑任务。
1.7 Netty 的应用场景
Netty 被广泛应用于多种领域包括但不限于
Web 服务器构建高性能的 HTTP 服务器。游戏服务器处理大量的玩家连接和游戏数据交换。即时通讯系统构建高并发的聊天应用。分布式系统作为基础的通信框架支撑大规模的分布式系统。大数据处理用于处理大规模的数据流。IoT 应用处理来自物联网大量设备的数据。
1.8 Netty 的重要组件
EventLoop负责处理 I/O 事件并执行与 Channel 相关联的任务。EventLoopGroup管理一组 EventLoop 实例为 Channel 提供一个或多个 EventLoop 供其使用。Channel代表一个网络连接用于进行数据的读取和写入操作。ChannelFuture代表一个异步操作的结果。ChannelFuture 提供了对异步操作完成状态的检查方法。ChannelPipeline用于处理入站和出站的数据流是一个责任链模式的实现。ChannelHandler处理具体的业务逻辑例如解码、编码、业务逻辑处理等。ByteBuf用于存储和操作二进制数据的缓冲区。ByteBuf 提供了高效的数据读写操作。Bootstrap用于创建新的 Channel配置 Channel 的参数和初始化 ChannelPipeline。
2. 第一个程序
2.1 目标
开发一个简单的服务器端和客户端
客户端向服务器端发送 hello, world服务器仅接收不返回
加入依赖
dependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.39.Final/version
/dependency2.2 服务器端
new ServerBootstrap().group(new NioEventLoopGroup()) // 1.channel(NioServerSocketChannel.class) // 2.childHandler(new ChannelInitializerNioSocketChannel() { // 3protected void initChannel(NioSocketChannel ch) {ch.pipeline().addLast(new StringDecoder()); // 5ch.pipeline().addLast(new SimpleChannelInboundHandlerString() { // 6Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) {System.out.println(msg);}});}}).bind(8080); // 4代码解读
1 处创建 NioEventLoopGroup可以简单理解为 线程池 Selector 后面会详细展开2 处选择服务 Scoket 实现类其中 NioServerSocketChannel 表示基于 NIO 的服务器端实现其它实现还有 3 处为啥方法叫 childHandler是接下来添加的处理器都是给 SocketChannel 用的而不是给 ServerSocketChannel。ChannelInitializer 处理器仅执行一次它的作用是待客户端 SocketChannel 建立连接后执行 initChannel 以便添加更多的处理器4 处ServerSocketChannel 绑定的监听端口5 处SocketChannel 的处理器解码 ByteBuf String6 处SocketChannel 的业务处理器使用上一个处理器的处理结果
完整代码
public class HelloServer {public static void main(String[] args) {// 1. 启动器负责组装 netty 组件启动服务器new ServerBootstrap()// 2. BossEventLoop, WorkerEventLoop(selector,thread)表示通过group加入了一个EventLoop的组//EventLoopGroup内部使用线程和选择器不断循环监听是否有新的事件.group(new NioEventLoopGroup())//一开始监听accept事件由其中的一个EventLoop进行处理accept事件//当接受到客户端发送的数据时触发read事件由某个EventLoop处理交给initChannel()中配置的处理器从上到下进行处理// 3. 选择服务器的ServerSocketChannel实现NioServerSocketChannel相当于对ServerSocketChannel做了封装.channel(NioServerSocketChannel.class) // 还支持OIO(OioServerSocketChannel)其实就是BIO// 4. boss 负责处理连接worker(child) 负责处理读写// childHandler决定了 worker(child) 能执行哪些操作/业务handler//注意这里只是添加了handler并没有执行initChannel()只有在连接建立后才会执行.childHandler(// 5. channel 代表和客户端进行数据读写的通道Initializer 初始化负责添加别的 handlernew ChannelInitializerNioSocketChannel() {//连接建立后调用该初始化方法initChannel()//当客户端连接后(触发了accept事件)运行initChannel()内代码Overrideprotected void initChannel(NioSocketChannel ch) throws Exception {// 添加具体 handlerch.pipeline().addLast(new LoggingHandler());ch.pipeline().addLast(new StringDecoder()); // 负责解码的ChannelHandler将ByteBuf转换为字符串ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { // 自定义 handlerOverride // 读事件public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception {System.out.println(msg); // 打印上一步(new StringDecoder())转换好的字符串}});}})// 6. 绑定监听端口.bind(8080);}
}2.3 客户端
new Bootstrap().group(new NioEventLoopGroup()) // 1.channel(NioSocketChannel.class) // 2.handler(new ChannelInitializerChannel() { // 3Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder()); // 8}}).connect(127.0.0.1, 8080) // 4.sync() // 5.channel() // 6.writeAndFlush(new Date() : hello world!); // 7代码解读
1 处创建 NioEventLoopGroup同 Server2 处选择客户 Socket 实现类NioSocketChannel 表示基于 NIO 的客户端实现其它实现还有 3 处添加 SocketChannel 的处理器ChannelInitializer 处理器仅执行一次它的作用是待客户端 SocketChannel 建立连接后执行 initChannel 以便添加更多的处理器4 处指定要连接的服务器和端口5 处Netty 中很多方法都是异步的如 connect这时需要使用 sync 方法等待 connect 建立连接完毕6 处获取 channel 对象它即为通道抽象可以进行数据读写操作7 处写入消息并清空缓冲区8 处消息会经过通道 handler 处理这里是将 String ByteBuf 发出数据经过网络传输到达服务器端服务器端 5 和 6 处的 handler 先后被触发走完一个流程
public class HelloClient {public static void main(String[] args) throws InterruptedException {// 1. 启动类启动客户端new Bootstrap()// 2. 添加 EventLoop.group(new NioEventLoopGroup())//如果服务器端发来数据客户端的EventLoop就可以从selector触发读事件进行处理// 3. 选择客户端 channel 实现底层封装了SocketChannel.channel(NioSocketChannel.class)// 4. 添加处理器.handler(new ChannelInitializerNioSocketChannel() {Override // 在连接建立后被调用protected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new StringEncoder());//编码器将字符串编码成ByteBuf进行发送}})// 5. 连接到服务器.connect(new InetSocketAddress(localhost, 8080)).sync()//sync()是一个阻塞方法只有连接建立后才会继续执行.channel()//.channel()表示拿到服务器和客户端之间的SocketChannel(连接对象)// 6. 向服务器发送数据.writeAndFlush(hello, world);}
}2.4 流程梳理 凡是收发数据都要走handler 客户端和服务器在连接建立后调用初始化方法(initChannel()方法)调用完初始化方法会将处理器(Handler)加载好下次发送数据时直接使用处理器。 提示
一开始需要树立正确的观念 把 channel 理解为数据的通道
把 msg 理解为流动的数据最开始输入是 ByteBuf但经过 pipeline 的加工会变成其它类型对象最后输出又变成 ByteBuf
把 handler 理解为数据的处理工序
工序有多道合在一起就是 pipelinepipeline 负责发布事件读、读取完成…传播给每个 handler handler 对自己感兴趣的事件进行处理重写了相应事件处理方法handler 分 Inbound 和 Outbound 两类
把 eventLoop 理解为处理数据的工人
工人可以管理多个 channel 的 io 操作并且一旦工人负责了某个 channel就要负责到底eventLoop绑定channel工人既可以执行 io 操作也可以进行任务处理每位工人有任务队列队列里可以堆放多个 channel 的待处理任务任务分为普通任务、定时任务(eventLoop底层使用了线程池只不过是单线程的线程池)工人按照 pipeline 顺序依次按照 handler 的规划代码处理数据可以为每道工序指定不同的工人 可以理解为Handler就是一道道工序对接受的原式数据进行加工处理 EventLoop内部是有一个selectorEventLoop通过多路复用可以管理多个channel的IO操作。