Netty

作者: 特仑苏纯牛乳 | 来源:发表于2019-10-29 18:18 被阅读0次

    1.Netty怎样切换三种经典的i/o模式
    BIO 阻塞 排队打饭模式 JDK1.4 之前
    NIO 非阻塞 点单等待被叫模式 JDK1.4 java.nio
    AIO 异步 包厢模式 JDK1.7 回调
    阻塞与非阻塞:是否等待数据就绪
    同步与异步:数据就绪后谁来操作的问题 异步由服务方在数据完成后进行回调操作数据
    Netty为什么仅保留了对NIO的支持

    Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用 epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!!!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!!!

    Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!!!

    1.1怎么切换
    1.2切换原理 泛型 反射 工厂
    1.3服务器开发为什么不需要切换客户端对应的socket

    什么是reactor及三种版本?


    image.png

    开发模式:


    image.png
    Reactor是一种开发模式,模式的核心流程:
    注册时间--->监听(扫描)时间是否发生--->事件发生后进行相应的处理
    image.png
    image.png
    image.png
    image.png
    image.png
    image.png

    netty如何支持主从reactor模式的?

    EchoServer
            // Configure the server.
            EventLoopGroup bossGroup = new NioEventLoopGroup(1);//main reactor
            EventLoopGroup workerGroup = new NioEventLoopGroup();         //sub  reactor
            ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)               //set main sub reactor
                 .channel(NioServerSocketChannel.class)
                 .option(ChannelOption.SO_BACKLOG, 100)
                 .handler(new LoggingHandler(LogLevel.INFO))
                 .childHandler(new ChannelInitializer<SocketChannel>() {
                     @Override
                     public void initChannel(SocketChannel ch) throws Exception {
                         ChannelPipeline p = ch.pipeline();
                         if (sslCtx != null) {
                             p.addLast(sslCtx.newHandler(ch.alloc()));
                         }
                         //p.addLast(new LoggingHandler(LogLevel.INFO));
                         p.addLast(serverHandler);
                     }
                 });
    
    public abstract class AbstractBootstrap<B extends AbstractBootstrap<B, C>, C extends Channel> implements Cloneable
    volatile EventLoopGroup group;
    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
            super.group(parentGroup);
            ObjectUtil.checkNotNull(childGroup, "childGroup");
            if (this.childGroup != null) {
                throw new IllegalStateException("childGroup set already");
            }
            this.childGroup = childGroup;
            return this;
        }
    //绑定main group
    ChannelFuture initAndRegister() {
    Channel channel = null;
            try {
                channel = channelFactory.newChannel();
                init(channel);
            } catch (Throwable t) {       .... }
    
            ChannelFuture regFuture = config().group().register(channel);
            if (regFuture.cause() != null) {
                if (channel.isRegistered()) {
                    channel.close();
                } else {
                    channel.unsafe().closeForcibly();
                }
            }
    }
    
    
    ServerBootStrap
     @Override
            @SuppressWarnings("unchecked")
            public void channelRead(ChannelHandlerContext ctx, Object msg) {
                final Channel child = (Channel) msg;
    
                child.pipeline().addLast(childHandler);
    
                setChannelOptions(child, childOptions, logger);
                setAttributes(child, childAttrs);
    
                try {
                    childGroup.register(child).addListener(new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) throws Exception {
                            if (!future.isSuccess()) {
                                forceClose(child, future.cause());
                            }
                        }
                    });
                } catch (Throwable t) {
                    forceClose(child, t);
                }
            }
    
    

    两种socketChannel(ServerSocketChannel、SocketChannel) 绑定到两个不同的group

    为什么说netty的main reactor大多并不能用到一个线程组,只能用线程组里的一个?

    服务器地址绑定的时候调用一次

     private ChannelFuture doBind(final SocketAddress localAddress) {
            final ChannelFuture regFuture = initAndRegister();
    ....
    }
    

    netty给channel分配NIO event loop的规则是什么?

    public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory
        @Override
        public EventExecutorChooser newChooser(EventExecutor[] executors) {
            if (isPowerOfTwo(executors.length)) {
                return new PowerOfTwoEventExecutorChooser(executors);
            } else {
                return new GenericEventExecutorChooser(executors);
            }
        }
    
    private static boolean isPowerOfTwo(int val) {
            return (val & -val) == val;
    
    因为数字在电脑中是以[补码]的形式存在的
    比如
    a = 10
    仅以8位举例
    正数
    a 原码 0000 1010 [补码]与原码相等 0000 1010
    负数 补码为 它绝对值的[反码]最后+1
    
        }
    
            @Override
            public EventExecutor next() {
                return executors[idx.getAndIncrement() & executors.length - 1];
            }
    
            @Override
            public EventExecutor next() {
                // 递增 取模 取正值
                return executors[Math.abs(idx.getAndIncrement() % executors.length)];
            }
    

    通用模式的NIO实现多路复用器是怎么跨平台的?

    JDK

    什么是粘包和半包?常用解决方法、Netty对三种常用封帧方式的支持

    粘包:一个包发送多个消息。 半包:消息被拆分多个包发送。
    粘包的主要原因:发送方每次写入数据小于套接字缓冲区大小;读取数据不够及时
    半包:发送方数据大于套接字大小;发送数据大于协议MTU时,必须拆包

    根本原因:TCP是一个流式协议,消息没有边界。UDP就没有这个问题。


    20191016200816.png image.png

    解码的核心工作流程是什么?

    channelRead(... ...)

    解码中两种数据积累器(cumulator)的区别?

    内存复制与组合

    三种解码器的常用额外控制参数有哪些?

    以上解码器(ByteToMeaageDecoder)主要是为了解决粘包与半包问题,得到一个正确的字节数组;
    二次解码器(MessageToMessageDecoder)(序列化与反序列化相关)

    keepalive与idle检测

    为什么需要keepalive、怎样设计keepalive、为什么还需要应用层keepalive、idle检测是什么、netty如何开启keepalive与idle检测


    image.png image.png

    为什么需要应用层keepalive


    image.png
    image.png image.png
    image.png
    image.png
    image.png

    相关文章

      网友评论

          本文标题:Netty

          本文链接:https://www.haomeiwen.com/subject/ydlemctx.html