Netty框架介绍及实战
Netty框架模型
NIO 的类库和API繁杂,使用麻烦:需要熟练掌握Selector、ServerSocket、ChannelSocketChannel、 ByteBuffer等。开发工作量和难度都非常大: 例如客户端面临断连重连、 网络闪断、心跳处理、半包读写、 网络拥塞和异常流的处理等等。
Netty 对 JDK 自带的 NIO 的 API 进行了良好的封装,解决了上述问题。且Netty拥有高性能、 吞吐量更高,延迟更低,减少资源消耗,最小化不必要的内存复制等优点。
Netty 现在都在用的是4.x,5.x版本已经废弃,Netty 4.x 需要JDK 6以上版本支持。
Netty的使用场景:
1)互联网行业:在分布式系统中,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用Netty 作为基础通信组件,用于实现。各进程节点之间的内部通信。Rocketmq底层也是用的Netty作为基础通信组件。
2)游戏行业:无论是手游服务端还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈。
3)大数据领域:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty进行跨界点通信,它的 Netty Service 基于 Netty 框架二次封装实现。
Netty线程模型
模型解释
- Netty抽象2个线程池,Boss Group和Work Group。Boss Group用于处理Accept事件,Work Group 用于处理 Read 和Write事件。
- Boss Group和Work Group都属于EventLoopGroup。
- NioEventLoopGroup 相当于一个事件循环线程组, 这个组中含有多个事件循环线程 , 每一个事件循环线程是NioEventLoop 。
- 每一个NioEventLoop都会有一个Selector用于监听绑定的Chanel
- Boss NioEventLoop的处理流程如下:
a. 进行accpet操作,返回SocketChanel
b.将该Socketchanel注册到某个work NioEventLoop的seletor上
c.处理任务队列的任务 , 即runAllTasks - Work NioEventLoop的处理流程如下:
a. 轮询所有注册到该Loop Seletor上的Socketchanel的Read/Write事件
b.处理Read/Write事件
c.runAllTasks处理任务队列TaskQueue的任务 ,一些耗时的业务处理一般可以放入
Netty 实战
写一个聊天室程序,服务端具备上线检测,群发聊天内容等。Netty极大的简化了NIO编程,开发者更多的是编写ChannelHandle逻辑做业务处理
服务端代码 Server
package com.qinghaihu.chat;import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;/**
* @ClassName ChatServer
* @Description TODO
* @Author:Zhang Lianzhong
* @Date 2020/11/22 10:13 下午
* @Version 1.0
**/
public class ChatServer {public void openServer(int port){ServerBootstrap bootstrap = new ServerBootstrap();EventLoopGroup boss = new NioEventLoopGroup(1); //create boss group, threadpool size is 1EventLoopGroup work = new NioEventLoopGroup(5); //create work group, threadpool size is 5bootstrap.group(boss,work); //组合netty组件//配置handle组件bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast("encoder",new StringEncoder());ch.pipeline().addLast("decoder",new StringDecoder());ch.pipeline().addLast(new ServerChanelHandle());}});bootstrap.channel(NioServerSocketChannel.class);try{ChannelFuture channel = bootstrap.bind(port).sync();System.out.println(("服务端已启动,绑定端口:" + port));channel.channel().closeFuture().sync();} catch (InterruptedException e) {e.printStackTrace();}finally {boss.shutdownGracefully();work.shutdownGracefully();}}public static void main(String[] args){ChatServer server = new ChatServer();server.openServer(8090);}}
服务端ChannelHandle
package com.qinghaihu.chat;import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;/*** @ClassName ServerChanelHandle* @Description TODO* @Author:Zhang Lianzhong* @Date 2020/11/22 10:21 下午* @Version 1.0**/
public class ServerChanelHandle extends SimpleChannelInboundHandler {//必须定义为类成员变量。每个客户端连接时,都会new ChatServerHandler。static保证数据共享public static ChannelGroup cg = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);@Overridepublic void handlerAdded(ChannelHandlerContext ctx) throws Exception {Channel ch = ctx.channel();for(Channel chanel: cg){chanel.writeAndFlush(ch.remoteAddress()+"进来啦!");}cg.add(ch);}/*** 上线处理* @param ctx* @throws Exception*/@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();for(Channel ch: cg){ch.writeAndFlush(channel.remoteAddress()+"上线啦");}}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {Channel channel = ctx.channel();for(Channel ch: cg){if(channel ==ch){ch.writeAndFlush("我说"+msg);}else {ch.writeAndFlush(channel.remoteAddress()+"说:"+msg);}}}@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();cg.remove(channel);}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {Channel channel = ctx.channel();String customerAddress = channel.remoteAddress().toString();for(Channel ch:cg){ch.writeAndFlush("客户端" + customerAddress + "下线了!");}}}
客户端Client
package com.qinghaihu.chat;import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;import java.util.Scanner;/*** @ClassName ChatClient* @Description TODO* @Author:Zhang Lianzhong* @Date 2020/11/22 10:54 下午* @Version 1.0**/
public class ChatClient implements Runnable{private String serverIP;private int port;public ChatClient(String serverIp,int port ){this.serverIP = serverIp;this.port = port;}@Overridepublic void run() {Bootstrap bootstrap = new Bootstrap();EventLoopGroup work = new NioEventLoopGroup(1);bootstrap.group(work);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast("encode",new StringEncoder());ch.pipeline().addLast("decode",new StringDecoder());ch.pipeline().addLast(new ClientChanelHandle());}});bootstrap.channel(NioSocketChannel.class);ChannelFuture channelFuture = bootstrap.connect(serverIP,port);Channel channel = channelFuture.channel();Scanner scanner = new Scanner(System.in);while(scanner.hasNext()){String sendMsg = scanner.nextLine();channel.writeAndFlush(sendMsg);}work.shutdownGracefully();}public static void main(String[] args){new Thread(new ChatClient("127.0.0.1",8090)).start();}
}
客户端ChannelHandle
package com.qinghaihu.chat;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;/*** @ClassName ClientChanelHandle* @Description TODO* @Author:Zhang Lianzhong* @Date 2020/11/22 11:08 下午* @Version 1.0**/
public class ClientChanelHandle extends SimpleChannelInboundHandler {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println(msg);}
}
运行效果
Netty框架介绍及实战相关推荐
- Netty介绍及实战(二)之IO与NIO和多路复用与零拷贝
Netty介绍及实战(一) 一.Netty到底是什么?什么是多路复用?什么叫做零拷贝? Netty是一个NIO客户端服务器框架,可以快速.轻松地开发协议服务器和客户端等网络应用程序.它极大地简化和简化 ...
- 【SpringBoot】Logback日志框架介绍和SpringBoot整合实战
========================11.Logback日志框架介绍和SpringBoot整合实战 2节课================================ 1.新日志框架L ...
- Netty介绍与实战(三)之粘包拆包
一.传统NIO架构 step1. 我们传统的nio架构已经解决了多路复用,零拷贝等问题,已经十分优秀了,那为什么我们现在Netty如此火热呢? 1) 首先他使用简单,基本上都是模板化,我们可以更专注业 ...
- 《企业级ios应用开发实战》一2.2 iOS框架介绍
2.2 iOS框架介绍 iOS衍生自Mac OS X的成熟内核,但iOS操作系统更紧凑和高效,支持iPhone和iPod Touch的硬件.iOS继承了Mac OS X的风格,包括:统一的OS X 内 ...
- 基于 Netty 网络编程项目实战课程
一 基于 Netty 网络编程项目实战课程 1项目介绍 2Netty 介绍与相关基础知识 2.1Netty 介绍 简介 Netty 是由 JBOSS 提供的一个 java 开源框架.Netty 提供异 ...
- 新浪微博新兵训练营系列课程——平台RPC框架介绍
新浪微博新兵训练营系列课程--平台RPC框架介绍 课程大纲 1.RPC简介 1.1 什么是RPC 1.2 RPC与其他远程调用方式比较 2.Motan RPC框架 2.1 RPC服务框架 2.2 Mo ...
- Netty框架架构解析+API+运行流程+网络编程文章集锦
新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析 <!-- 作者区域 --><div class="author"><a class=& ...
- ssm 异常捕获 统一处理_SpringMVC 统一异常处理介绍及实战
背景 什么是统一异常处理 目标 统一异常处理实战 用 Assert(断言) 替换 throw exception 定义统一异常处理器类 扩展 总结 <Java 2019 超神之路> < ...
- 【分布式事务】tcc-transaction分布式TCC型事务框架搭建与实战案例(基于Dubbo/Dubbox)...
一.背景 有一定分布式开发经验的朋友都知道,产品/项目/系统最初为了能够快速迭代上线,往往不太注重产品/项目/系统的高可靠性.高性能与高扩展性,采用单体应用和单实例数据库的架构方式快速迭代开发:当产品 ...
- 【Netty】Netty组件介绍
Netty组件介绍 Netty有 Bootstrap/ServerBootstrap,Channel,EventLoop,ChannelFuture, ChannelHandler,ChannelPi ...
最新文章
- 王树彤IT美女七年磨一剑
- php的VC9-VC14运行库分享以及localhost访问404问题
- Spring Cloud:查看注册到Eureka上的应用信息
- mysql容器重启数据是否丢失_docker容器重启 数据会丢吗
- [LAMP]——mod_security和mod_evasive模块的安装
- python中yield讲解_「技术」如何深入理解Python中的 yield?
- matlab2c使用c++实现matlab函数系列教程-ones函数
- Shell命令-系统信息及显示之stat、du
- 118页/8万字重磅(附下载)| 全球智能网联汽车产业深度报告:未来已来 掘金智能网联汽车时代【华西汽车 崔琰团队】
- 开源软件、自由软件及免费软件的区别
- 10种常用数据分析方法
- VS Code插件安装位置
- 在pycharm中使用pyqt5时clicked().后面connect不自动补全问题解决办法
- 数位板使用技巧、个人数位板见解、插画教程...
- 企业人脸识别智能门禁系统解决方案
- ArcGIS jsAPI 本地部署字体符号乱码
- python罗盘时钟代码_jQuery css3创意的罗盘时钟代码
- Python爬虫:爬了7天的斗鱼,我们来看一下主播们的真实现状
- WPF的打印原理 实现打印页眉页脚和打印预览
- 屏蔽 app 开屏广告,舒畅了