Netty源碼分析:ServerBootstrap
一般服務端的代碼如下所示:
package com.wrh.server;
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;
/**
* Created by wuranghao on 2017/9/4.
*/
public final class SimpleServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new SimpleServerHandler())
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
}
});
ChannelFuture f = b.bind(8888).sync();
f.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private static class SimpleServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelRegistered");
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded");
}
}
}
在上篇博文(http://blog.csdn.net/u010412719/article/details/78006968)中 剖析瞭如下的兩行代碼內部的構造函數中幹了些什麼。
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
具體可以見上篇博文,對於如上的兩行代碼得到的結論是:
1、 如果不指定線程數,則線程數爲:CPU的核數*2
2、根據線程個數是否爲2的冪次方,採用不同策略初始化chooser
3、產生nThreads個NioEventLoop對象保存在children數組中。
可以理解NioEventLoop就是一個線程,線程NioEventLoop中裏面有如下幾個屬性:
1、NioEventLoopGroup (在父類SingleThreadEventExecutor中)
2、selector
3、provider
4、thread (在父類SingleThreadEventExecutor中)
更通俗點就是: NioEventLoopGroup就是一個線程池,NioEventLoop就是一個線程。NioEventLoopGroup線程池中有N個NioEventLoop線程。
ServerBootstrap類分析
本篇博文將分析如下幾行代碼裏面做了些什麼。
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new SimpleServerHandler())
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
}
});
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;
private volatile ChannelHandler childHandler;
其父類AbstractBootstrap的參數
private volatile EventLoopGroup group;
private volatile ChannelFactory<? extends C> channelFactory;
private volatile SocketAddress localAddress;
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
private final Map<AttributeKey<?>, Object> attrs = new LinkedHashMap<AttributeKey<?>, Object>();
private volatile ChannelHandler handler;
ServerBootstrap類的無參構造函數什麼都沒有做,這沒什麼好說的。下面主要看下這個鏈式設置相關的參數。
1)group(bossGroup, workerGroup):設置group
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup);
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) {
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup;
return this;
}
即將workerGroup保存在 ServerBootstrap對象的childGroup屬性上。 bossGroup保存在ServerBootstrap對象的group屬性上
2)channel(NioServerSocketChannel.class)
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;
}
函數功能:設置父類屬性channelFactory 爲: BootstrapChannelFactory類的對象。其中這裏BootstrapChannelFactory對象中包括一個clazz屬性爲:NioServerSocketChannel.class,從如下該類的構造函數中可以明顯的得到這一點。
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 {
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";
}
}
3)handler(new SimpleServerHandler())
此方法的具體代碼如下:
public B handler(ChannelHandler handler) {
if (handler == null) {
throw new NullPointerException("handler");
}
this.handler = handler;
return (B) this;
}
函數功能:設置handler屬性,該屬性在其父類 AbstractBootstrap中。
注意:這裏的handler函數的入參類是我們自己提供的。如下,後面的博文中將會分析這個handler將會在哪裏以及何時被調用,這裏只需要記住這一點即可
private static class SimpleServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelActive");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channelRegistered");
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handlerAdded");
}
}
4)childHandler
public ServerBootstrap childHandler(ChannelHandler childHandler) {
if (childHandler == null) {
throw new NullPointerException("childHandler");
}
this.childHandler = childHandler;
return this;
}
簡單來說就是將如下的childHandler設置在AbstractBootstrap的相應屬性上。
childHandler = new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
}
})
總結
比較簡單哈,主要是將我們提供的參數設置到其相應的對象屬性中去了。 因爲後面會用到如下的幾個屬性,因此最好知道下,這些屬性是何時以及在那裏賦值的。以免分析到後面會很懵逼。
1、group:workerGroup保存在 ServerBootstrap對象的childGroup屬性上。 bossGroup保存在ServerBootstrap對象的group屬性上
2、channelFactory:BootstrapChannelFactory類的對象(clazz屬性爲:NioServerSocketChannel.class)
3、handler:SimpleServerHandler
4、childHandler