0


Netty学习笔记之线程模型【上】

  • 💖大家好,我是 爪哇小白2021
  • 半路出家的程序员,在从事开发之前在 某省测绘院 玩了一年的飞机,机缘巧合之下发现了更有趣的事情,从此步入了编程的世界… ps:同时也是一个热爱旅行的航拍小能手!
  • 💬 目的:记录自己的学习历程,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🖊

Netty

Netty 对 JDK 自带的 NIO 的 API 进行了良好的封装,解决了上述问题。且 Netty 拥有高性能、吞吐量更高,延迟更低,减少资源消耗,最小化不必要的内存复制等优点。
Netty 现在用的是 4.x,5.x 版本已经废弃,Netty4.x 需要 JDK6 以上版本支持。

场景

互联网行业

:在分布式系统中,各个节点之间需要远程服务调用,高性能的 RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。典型应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现。各进程节点之间的内部通信。RocketMQ 底层也是用的 Netty 作为基础通信组件。

游戏行业

:无论是手游服务端还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty 作为高性能的基础通信组件,它本身提供了 TCP/UDP 和 HTTP 协议栈。

大数据领域

:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨界点通信,它的 Netty Service 基于 Netty 框架二次封装实现。

说到这就是说netty还是值得去深入学习一番的~
在这里插入图片描述

通讯示例-代码展示

Maven 依赖:

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.35.Final</version></dependency>

服务端代码:

publicclassNettyServer{publicstaticvoidmain(String[] args)throwsException{//创建两个线程组bossGroup和workerGroup, 含有的子线程NioEventLoop的个数默认为cpu核数的两倍// bossGroup只是处理连接请求 ,真正的和客户端业务处理,会交给workerGroup完成EventLoopGroup bossGroup =newNioEventLoopGroup(1);EventLoopGroup workerGroup =newNioEventLoopGroup();try{//创建服务器端的启动对象ServerBootstrap bootstrap =newServerBootstrap();//使用链式编程来配置参数
            bootstrap.group(bossGroup, workerGroup)//设置两个线程组.channel(NioServerSocketChannel.class)//使用NioServerSocketChannel作为服务器的通道实现// 初始化服务器连接队列大小,服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。// 多个客户端同时来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理.option(ChannelOption.SO_BACKLOG,1024).childHandler(newChannelInitializer<SocketChannel>(){//创建通道初始化对象,设置初始化参数@OverrideprotectedvoidinitChannel(SocketChannel ch)throwsException{//对workerGroup的SocketChannel设置处理器
                            ch.pipeline().addLast(newNettyServerHandler());}});System.out.println("netty server start。。");//绑定一个端口并且同步, 生成了一个ChannelFuture异步对象,通过isDone()等方法可以判断异步事件的执行情况//启动服务器(并绑定端口),bind是异步操作,sync方法是等待异步操作执行完毕ChannelFuture cf = bootstrap.bind(9000).sync();//给cf注册监听器,监听我们关心的事件/*cf.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (cf.isSuccess()) {
                        System.out.println("监听端口9000成功");
                    } else {
                        System.out.println("监听端口9000失败");
                    }
                }
            });*///对通道关闭进行监听,closeFuture是异步操作,监听通道关闭// 通过sync方法同步等待通道关闭处理完毕,这里会阻塞等待通道关闭完成
            cf.channel().closeFuture().sync();}finally{
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();}}}/**
 * 自定义Handler需要继承netty规定好的某个HandlerAdapter(规范)
 */publicclassNettyServerHandlerextendsChannelInboundHandlerAdapter{/**
     * 读取客户端发送的数据
     *
     * @param ctx 上下文对象, 含有通道channel,管道pipeline
     * @param msg 就是客户端发送的数据
     * @throws Exception
     */@OverridepublicvoidchannelRead(ChannelHandlerContext ctx,Object msg)throwsException{System.out.println("服务器读取线程 "+Thread.currentThread().getName());//Channel channel = ctx.channel();//ChannelPipeline pipeline = ctx.pipeline(); //本质是一个双向链接, 出站入站//将 msg 转成一个 ByteBuf,类似NIO 的 ByteBufferByteBuf buf =(ByteBuf) msg;System.out.println("客户端发送消息是:"+ buf.toString(CharsetUtil.UTF_8));}/**
     * 数据读取完毕处理方法
     *
     * @param ctx
     * @throws Exception
     */@OverridepublicvoidchannelReadComplete(ChannelHandlerContext ctx)throwsException{ByteBuf buf =Unpooled.copiedBuffer("HelloClient",CharsetUtil.UTF_8);
        ctx.writeAndFlush(buf);}/**
     * 处理异常, 一般是需要关闭通道
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */@OverridepublicvoidexceptionCaught(ChannelHandlerContext ctx,Throwable cause)throwsException{
        ctx.close();}}

客户端代码:

publicclassNettyClient{publicstaticvoidmain(String[] args)throwsException{//客户端需要一个事件循环组EventLoopGroup group =newNioEventLoopGroup();try{//创建客户端启动对象//注意客户端使用的不是 ServerBootstrap 而是 BootstrapBootstrap bootstrap =newBootstrap();//设置相关参数
            bootstrap.group(group)//设置线程组.channel(NioSocketChannel.class)// 使用 NioSocketChannel 作为客户端的通道实现.handler(newChannelInitializer<SocketChannel>(){@OverrideprotectedvoidinitChannel(SocketChannel channel)throwsException{//加入处理器
                            channel.pipeline().addLast(newNettyClientHandler());}});System.out.println("netty client start");//启动客户端去连接服务器端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",9000).sync();//对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();}finally{
            group.shutdownGracefully();}}}publicclassNettyClientHandlerextendsChannelInboundHandlerAdapter{/**
     * 当客户端连接服务器完成就会触发该方法
     *
     * @param ctx
     * @throws Exception
     */@OverridepublicvoidchannelActive(ChannelHandlerContext ctx)throwsException{ByteBuf buf =Unpooled.copiedBuffer("HelloServer",CharsetUtil.UTF_8);
        ctx.writeAndFlush(buf);}//当通道有读取事件时会触发,即服务端发送数据给客户端@OverridepublicvoidchannelRead(ChannelHandlerContext ctx,Object msg)throwsException{ByteBuf buf =(ByteBuf) msg;System.out.println("收到服务端的消息:"+ buf.toString(CharsetUtil.UTF_8));System.out.println("服务端的地址: "+ ctx.channel().remoteAddress());}@OverridepublicvoidexceptionCaught(ChannelHandlerContext ctx,Throwable cause)throwsException{
        cause.printStackTrace();
        ctx.close();}}

总结

Netty 框架的目的就是让你的业务逻辑从网络基础应用编码中分离出来,让你可以专注业务的开发,而不需要写一大堆类似 NIO 的网络处理操作。

标签: rpc java 分布式

本文转载自: https://blog.csdn.net/m0_56368068/article/details/122919383
版权归原作者 爪哇小白2021 所有, 如有侵权,请联系我们删除。

“Netty学习笔记之线程模型【上】”的评论:

还没有评论