Netty服务端启动解析

 

开启一个服务端,端口绑定在port,使用nio模式

 

public class NettyDemoServer {

    private final int port;

    public NettyDemoServer(int port){

        this.port = port;

    }

    public void start() throws Exception {

        EventLoopGroup workgroup = new NioEventLoopGroup();

        EventLoopGroup boosGroup = new NioEventLoopGroup(1);

        try {

            ServerBootstrap bootstrap = new ServerBootstrap();

            bootstrap.group(boosGroup,workgroup)

                     .channel(NioServerSocketChannel.class)

                     .localAddress(port)

                     .handler(new NettyDemoServerHandler())

                     .childHandler(new ChannelInitializer<Channel>() {

                @Override

                protected void initChannel(Channel channel) throws Exception {

                    channel.pipeline().addLast(new NettyDemoServerHandler());

                }

            });

            ChannelFuture future = bootstrap.bind().sync();

            System.out.println(NettyDemoServer.class.getName() +" started and listen on " + future.channel().localAddress());

            future.channel().closeFuture().sync();

        }catch (Exception e){

            workgroup.shutdownGracefully().sync();

            boosGroup.shutdownGracefully().sync();

        }

    }

    public class NettyDemoServerHandler extends ChannelInboundHandlerAdapter {

        @Override

        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

            ByteBuf in = (ByteBuf) msg;

            System.out.println("server received: " + in.toString(CharsetUtil.UTF_8));

            ctx.write(msg);

        }

        @Override

        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

            ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);

        }

        @Override

        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

            cause.printStackTrace();

            ctx.close();

        }

    }

}

 

EventLoopGroup初始化

//处理IO事件

EventLoopGroup workgroup = new NioEventLoopGroup();

//处理TCP链接请求

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

 

构造函数

public NioEventLoopGroup(int nThreads, ThreadFactory threadFactory,

    final SelectorProvider selectorProvider, final SelectStrategyFactory selectStrategyFactory) {

    super(nThreads, threadFactory, selectorProvider, selectStrategyFactory, RejectedExecutionHandlers.reject());

}

调用父类MultithreadEventLoopGroup的构造函数

protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {

    super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);

}

 

//设置默认的线程数

private static final int DEFAULT_EVENT_LOOP_THREADS;

 

static {

    DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(

            "io.netty.eventLoopThreads", NettyRuntime.availableProcessors() * 2));

 

    if (logger.isDebugEnabled()) {

        logger.debug("-Dio.netty.eventLoopThreads: {}", DEFAULT_EVENT_LOOP_THREADS);

    }

}

 

调用父类MultithreadEventExecutorGroup的构造函数

 

做了三件事情:

1.产生了一个线程工场:threadFactory = newDefaultThreadFactory();

protected ThreadFactory newDefaultThreadFactory() {

    return new DefaultThreadFactory(this.getClass());  //NioEventLoopGroup.class

}

 

2.选择策略:数组长度是2的幂次方,选择PowerOfTwoEventExecutorChooser,在选EventExecutor时使用children[idx.getAndIncrement() & executors.length - 1];如果数组长度不是2的幂次方,选择GenericEventExecutorChooser,children[Math.abs(idx.getAndIncrement() % executors.length)].

private final EventExecutor[] children;

children = new SingleThreadEventExecutor[nThreads];

if (isPowerOfTwo(this.children.length)) {

    this.chooser = new MultithreadEventExecutorGroup.PowerOfTwoEventExecutorChooser();

} else {

    this.chooser = new MultithreadEventExecutorGroup.GenericEventExecutorChooser();

}

 

 

3.产生nTreads个NioEventLoop对象保存在children数组中 

this.children[i] = this.newChild(threadFactory, args);

 

//在NioEventLoopGroup重载

@Override

protected EventExecutor newChild(

        ThreadFactory threadFactory, Object... args) throws Exception {

    return new NioEventLoop(this, threadFactory, (SelectorProvider) args[0]);

}

 

追溯到SingleThreadEventExecutor:

1、利用ThreadFactory创建一个Thread,传入了一个Runnable对象,调用NioEventLoop类的run方法

2、使用LinkedBlockingQueue类初始化taskQueue :执行任务

protected SingleThreadEventExecutor(

        EventExecutorGroup parent, ThreadFactory threadFactory, boolean addTaskWakesUp) {

    ...

    thread = threadFactory.newThread(new Runnable() {

        @Override

        public void run() {

           ...

            try {

                SingleThreadEventExecutor.this.run();

                success = true;

            } catch (Throwable t) {

                logger.warn("Unexpected exception from an event executor: ", t);

            } finally {

                ...

            }

        }

    });

 

    taskQueue = newTaskQueue();

}

 

protected Queue<Runnable> newTaskQueue() {

    return new LinkedBlockingQueue<Runnable>();

}

 

 

@Override

protected void run() {

    for (;;) {

        // 获取之前的线程状态,并让 select 阻塞

        boolean oldWakenUp = wakenUp.getAndSet(false);

        try {

            // return !taskQueue.isEmpty();

            if (hasTasks()) {

                selectNow();

            } else {

//1.首先轮询注册到NioEventLoop线程的selector上的所有的channel的IO事件

                // 自旋进行等待可进行 select 操作

                select(oldWakenUp);

                //唤醒线程

                if (wakenUp.get()) {

                    selector.wakeup();

                }

            }

 

            cancelledKeys = 0;

            needsToSelectAgain = false;

            final int ioRatio = this.ioRatio;

            //处理 selected 的通道的数据,并执行所有的任务

            if (ioRatio == 100) {

//2.处理产生网络IO事件的channel

                processSelectedKeys();

//3.处理任务队列

                runAllTasks();

            } else {

                final long ioStartTime = System.nanoTime();

 

                processSelectedKeys();

 

                final long ioTime = System.nanoTime() - ioStartTime;

                runAllTasks(ioTime * (100 - ioRatio) / ioRatio);

            }

 

            if (isShuttingDown()) {

                closeAll();

                if (confirmShutdown()) {

                    break;

                }

            }

        } catch (Throwable t) {

            logger.warn("Unexpected exception in the selector loop.", t);

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

            }

        }

    }

}}

 

4.children数组中每个EventExecutor绑定监听事件

 terminatedChildren

final FutureListener<Object> terminationListener = new FutureListener<Object>() {

    @Override

    public void operationComplete(Future<Object> future) throws Exception {

        if (terminatedChildren.incrementAndGet() == children.length) {

            terminationFuture.setSuccess(null);

        }

    }

};

 

for (EventExecutor e: children) {

    e.terminationFuture().addListener(terminationListener);

}

ServerBootstrap

服务端的一个启动辅助类,通过给他设置一系列参数来绑定端口启动服务

ServerBootstrap bootstrap = new ServerBootstrap();

       bootstrap.group(boosGroup,workgroup).channel(NioServerSocketChannel.class).localAddress(port).childHandler(new ChannelInitializer<Channel>() {

                @Override

                protected void initChannel(Channel channel) throws Exception {

                    channel.pipeline().addLast(new NettyDemoServerHandler());

                }

            });

 

ServerBootstrap类参数

private final Map<ChannelOption<?>, Object> childOptions = new LinkedHashMap<ChannelOption<?>, Object>();

private final Map<AttributeKey<?>, Object> childAttrs = new LinkedHashMap<AttributeKey<?>, Object>();

private volatile EventLoopGroup childGroup;  //workGroup

private volatile ChannelHandler childHandler; //new ChannelInitializer

父类AbstractBootstrap类参数

private volatile EventLoopGroup group;     //boosGroup

private volatile ChannelFactory<? extends C> channelFactory;

private volatile SocketAddress localAddress; //port

private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();

private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();

private volatile ChannelHandler handler;   //NettyDemoServerHandler()

 

group(boosGroup,workgroup)

public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {

    super.group(parentGroup); //boosGroup

    if (childGroup == null) {

        throw new NullPointerException("childGroup");

    }

    if (this.childGroup != null) {

        throw new IllegalStateException("childGroup set already");

    }

    this.childGroup = childGroup;

    return this;

}

 

channel(NioServerSocketChannel.class)

设置父类属性channelFactory 为: BootstrapChannelFactory类的对象

public B channel(Class<? extends C> channelClass) {

    if (channelClass == null) {

        throw new NullPointerException("channelClass");

    }

    return channelFactory(new BootstrapChannelFactory<C>(channelClass));

}

 

public B channelFactory(ChannelFactory<? extends C> channelFactory) {

    if (channelFactory == null) {

        throw new NullPointerException("channelFactory");

    }

    if (this.channelFactory != null) {

        throw new IllegalStateException("channelFactory set already");

    }

 

    this.channelFactory = channelFactory;

    return (B) this;

}

 

private static final class BootstrapChannelFactory<T extends Channel> implements ChannelFactory<T> {

    private final Class<? extends T> clazz;

 

    BootstrapChannelFactory(Class<? extends T> clazz) {

        this.clazz = clazz;

    }

 

    @Override

    public T newChannel() {

        try {

//通过反射来实例化NioServerSocketChannel.class

            return clazz.newInstance();

        } catch (Throwable t) {

            throw new ChannelException("Unable to create Channel from class " + clazz, t);

        }

    }

 

    @Override

    public String toString() {

        return StringUtil.simpleClassName(clazz) + ".class";

    }

}

 

localAddress(port)

设置监听端口

public B localAddress(int inetPort) {

    return localAddress(new InetSocketAddress(inetPort));

}

public B localAddress(SocketAddress localAddress) {

    this.localAddress = localAddress;

    return (B) this;

}

 

handler(new NettyDemoServerHandler())

设置父类 AbstractBootstrap的handle属性

public B handler(ChannelHandler handler) {

    if (handler == null) {

        throw new NullPointerException("handler");

    }

    this.handler = handler;

    return (B) this;

}

 

public class NettyDemoServerHandler extends ChannelInboundHandlerAdapter {

    @Override

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf in = (ByteBuf) msg;

        System.out.println("server received: " + in.toString(CharsetUtil.UTF_8));

        ctx.write(msg);

    }

    @Override

    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);

    }

    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        cause.printStackTrace();

        ctx.close();

    }

}

 

childHandle

设置childHandler

public ServerBootstrap childHandler(ChannelHandler childHandler) {

    if (childHandler == null) {

        throw new NullPointerException("childHandler");

    }

    this.childHandler = childHandler;

    return this;

}

 

启动服务

ChannelFuture future = bootstrap.bind().sync();

 

//AbstractBootstrap类

public ChannelFuture bind() {

    validate();

    SocketAddress localAddress = this.localAddress;

    if (localAddress == null) {

        throw new IllegalStateException("localAddress not set");

    }

    return doBind(localAddress);

}

 

private ChannelFuture doBind(final SocketAddress localAddress) {

    //实例一个ChannelFuture

    final ChannelFuture regFuture = initAndRegister();

    //ChannelFuture通过反射产生一个NioServerSocketChannel类的实例

    final Channel channel = regFuture.channel();

    //异常检查

    if (regFuture.cause() != null) {

        return regFuture;

    }

 

    final ChannelPromise promise;

//绑定socket

    if (regFuture.isDone()) {

        promise = channel.newPromise();

        doBind0(regFuture, channel, localAddress, promise);

    } else {

        promise = new PendingRegistrationPromise(channel);

        regFuture.addListener(new ChannelFutureListener() {

            @Override

            public void operationComplete(ChannelFuture future) throws Exception {

                doBind0(regFuture, channel, localAddress, promise);

            }

        });

    }

 

    return promise;

}

 

initAndRegister()

1、通过反射产生了一个NioServerSocketChannle对象

2、完成了channel初始化

3、将NioServerSocketChannel进行了注册

final ChannelFuture initAndRegister() {

//通过反射产生来一个NioServerSocketChannel类的实例

//在父类构造函数中SelectableChannel.configureBlocking(false);设置当前的ServerSocketChannel为非阻塞

    final Channel channel = channelFactory().newChannel();

    try {

        init(channel);

    } catch (Throwable t) {

        channel.unsafe().closeForcibly();

//用来负责底层的connect、register、read和write等操作。

       return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);

    }

//调用了NioEventLoop对象中的register方法,把channel绑定到NioEventLoop

    ChannelFuture regFuture = group().register(channel);

    if (regFuture.cause() != null) {

        if (channel.isRegistered()) {

            channel.close();

        } else {

            channel.unsafe().closeForcibly();

        }

    }

    return regFuture;

}

 

 

AbstractBootstrap类

private static void doBind0(

        final ChannelFuture regFuture, final Channel channel,

        final SocketAddress localAddress, final ChannelPromise promise) {

// 提交一个Runnable任务到NioEventLoop线程中来进行处理

    channel.eventLoop().execute(new Runnable() {

        @Override

        public void run() {

            if (regFuture.isSuccess()) {

//调用AbstractChannel类的bind方法,实现channel与端口的绑定

                channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE);

            } else {

                promise.setFailure(regFuture.cause());

            }

        }

    });

}

 

追溯到NioServerSocketChannel:

//通过JDK调用channel socket的bind函数绑定服务器端口号

protected void doBind(SocketAddress localAddress) throws Exception {

    if (PlatformDependent.javaVersion() >= 7) {

        javaChannel().bind(localAddress, config.getBacklog());

    } else {

        javaChannel().socket().bind(localAddress, config.getBacklog());

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值