Netty学习第四章--spring boot整合netty的使用

  现在大多数项目都是基于spring boot进行开发,所以我们以spring boot作为开发框架来使用netty。使用spring boot的一个好处就是能给将netty的业务拆分出来,并通过spring cloud整合到项目中。

  我们以一个简单的客户端发送消息到服务的场景编写一个实例。

一、服务端模块

  netty中服务端一般分为两个类,一个是启动配置类,另一个是消息的逻辑处理类

  1.启动配置类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

/**
 * Netty
 * 服务端
 */
@Configuration
public class NettyServer {

    //四个处理请求的逻辑类
    @Autowired
    ServerInboundHandler serverInboundHandler;

    @Autowired
    ServerInboundGetTimeHandler serverInboundGetTimeHandler;

    @Autowired
    ServerLastOutboundHandler serverLastOutboundHandler;

    @Autowired
    ServerOutboundHandler serverOutboundHandler;

    public void startServer() {
        System.out.println("服务端启动成功");
        //创建两个线程组,用于接收客户端的请求任务,创建两个线程组是因为netty采用的是反应器设计模式
        //反应器设计模式中bossGroup线程组用于接收
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        //workerGroup线程组用于处理任务
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        //创建netty的启动类
        ServerBootstrap bootstrap = new ServerBootstrap();
        //创建一个通道
        ChannelFuture f = null;
        try {
            bootstrap.group(bossGroup, workerGroup) //设置线程组
                    .channel(NioServerSocketChannel.class) //设置通道为非阻塞IO
                    .option(ChannelOption.SO_BACKLOG, 128) //设置日志
                    .option(ChannelOption.SO_RCVBUF, 32 * 1024)  //接收缓存
                    .childOption(ChannelOption.SO_KEEPALIVE, true)//是否保持连接
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        //设置处理请求的逻辑处理类
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //ChannelPipeline是handler的任务组,里面有多个handler
                            ChannelPipeline pipeline = ch.pipeline();
                            //逻辑处理类
                            pipeline.addLast(serverLastOutboundHandler);
                            pipeline.addLast(serverOutboundHandler);
                            pipeline.addLast(serverInboundHandler);
                            pipeline.addLast(serverInboundGetTimeHandler);
                        }
                    });

            f = bootstrap.bind(84).sync();//阻塞端口号,以及同步策略
            f.channel().closeFuture().sync();//关闭通道
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //优雅退出
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }


}

  2.启动配置类中的各个组件

  1)EventLoop 与 EventLoopGroup 

  EventLoop 好比一个线程,1个EventLoop 可以服务多个channel,而一个channel只会有一个EventLoop 。EventLoop 在netty中就是负责整个IO操作,包括从消息的读取、编码以及后续 ChannelHandler 的执行,这样做的好处就是避免了线程中的上下文切换时,大量浪费资源情况。

  EventLoopGroup 是负责分配EventLoop到新创建的channel,EventLoopGroup 就好比线程池,它里面包含多个EventLoop。

  2)BootStrap

  BootStrap 是netty中的引导启动类也就是一个工厂配置类,可以通过它来完成 Netty 的客户端或服务器端的 Netty 初始化,所以我们主要来看它的几个常用的配置方法。

  ① gruop() 方法

  gruop()方法用于配置netty中的线程组,也就是我们的EventLoopGroup ,在服务端中需要配置两个线程组,这是因为netty中采用的是反应器设计模式(reactor ),我们知道反应器设计模式中是需要两个线程组,一个用于接收用户的请求,另一个用于处理请求的内容。

  ② channel() 方法

  channel()方法用于配置通道的IO类型,IO类型有两个:阻塞IO(BIO)OioServerSocketChannel;非阻塞IO(NIO)NioServerSocketChannel。

  ③ childHandler () 方法

扫描二维码关注公众号,回复: 8062494 查看本文章

  用于设置处理请求的适配器,这个在下面详细介绍。

  ④ childOption() 方法

  给每条child channel连接设置一些TCP底层相关的属性,比如上面,我们设置了两种TCP属性,其中 ChannelOption.SO_KEEPALIVE表示是否开启TCP底层心跳机制,true为开

  ⑤ option

  给每条parent channel 连接设置一些TCP底层相关的属性。

  关于option的属性有:

  SO_RCVBUF ,SO_SNDBUF:用于设置TCP连接中使用的两个缓存区。

  TCP_NODELAY:立即发送数据,采用的是Nagle算法。Nagle算法是当小数据过多时,就会将这些小数据碎片连接成更大的报文,从而保证发送的报文数量最小。所以如果数据量小就要禁用这个算法,netty默认是禁用的值为true。

  通俗地说,如果要求高实时性,有数据发送时就马上发送,就关闭,如果需要减少发送次数减少网络交互,就开启。

  SO_KEEPALIVE:底层TCP协议的心跳机制。Socket参数,连接保活,默认值为False。启用该功能时,TCP会主动探测空闲连接的有效性。

  SO_REUSEADDR:Socket参数,地址复用,默认值False

  SO_LINGER:Socket参数,关闭Socket的延迟时间,默认值为-1,表示禁用该功能。

  SO_BACKLOG:Socket参数,服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝。默认值,Windows为200,其他为128。

  SO_BROADCAST:Socket参数,设置广播模式。

  3)ChannelFuture 

  我们知道netty中的所有IO操作都是异步的,这意味着任何IO调用都会立即返回,不管结果如果状态如果。而ChannelFuture 的存在就是为了解决这一问题,它会提供IO操作中有关的信息、结果或状态。

  ChannelFuture 一共有两个状态:

  未完成状态:当IO操作开始时,将创建一个新的ChannelFuture 对象,此时这个对象既没有操作成功也没有失败,那么就说这个对象就是未完成的状态。简单来说未完成指创建了对象且没有完成IO操作。

  已完成状态:当IO操作完成后,不管操作是成功还是失败,future都是标记已完成的,失败时也会有对应的具体失败信息。

2.消息逻辑处理类  

  可以看到我一共在pipeline里面配置了4个handler,这是为了查看inboundhandler和呕吐boundhandler的执行顺序

猜你喜欢

转载自www.cnblogs.com/daijiting/p/11975579.html
今日推荐