服务器启动源码
查看流程
// 通过nio方式来接收连接和处理连接
private EventLoopGroup bg = new NioEventLoopGroup();
private EventLoopGroup wg = new NioEventLoopGroup();
//启动引导器
private ServerBootstrap b = new ServerBootstrap();
//1 设置reactor 线程
b.group(bg, wg);
//2 设置nio类型的channel
b.channel(NioServerSocketChannel.class);
//3 设置监听端口
String ip = IOUtil.getHostAddress();
b.localAddress(new InetSocketAddress(ip, port));
//4 设置通道选项,传入TCP参数放入一个LinkedHashMap
b.option(ChannelOption.SO_KEEPALIVE, true);
b.option(ChannelOption.ALLOCATOR,
PooledByteBufAllocator.DEFAULT);
//5 装配流水线,传入一个handler,在每个客户端连接的时候调用
b.childHandler(new ChannelInitializer<SocketChannel>() {
//有连接到达时会创建一个channel
protected void initChannel(SocketChannel ch) throws Exception {
// 管理pipeline中的Handler
ch.pipeline().addLast("deCoder",new ProtobufDecoder());
ch.pipeline().addLast("enCoder",new ProtobufEncoder());
ch.pipeline().addLast("heartBeat",new HeartBeatServerHandler());
}
});
// 6 开始绑定server
// 通过调用sync同步方法阻塞直到绑定成功
ChannelFuture channelFuture = null;
boolean isStart = false;
while (!isStart) {
try {
channelFuture = b.bind().sync();
isStart = true;
} catch (Exception e) {
log.error("发生启动异常", e);
port++;
log.info("尝试一个新的端口:" + port);
b.localAddress(new InetSocketAddress(port));
}
}
ImWorker.getInst().setLocalNode(ip, port);
FutureTaskScheduler.add(() -> {
/**
* 启动节点
*/
ImWorker.getInst().init();
/**
* 启动节点的管理
*/
PeerManager.getInst().init();
});
try {
// 7 监听通道关闭事件
// 应用程序会一直等待,直到channel关闭
ChannelFuture closeFuture =
channelFuture.channel().closeFuture();
closeFuture.sync();
} catch (
Exception e) {
log.error("发生其他异常", e);
} finally {
// 8 优雅关闭EventLoopGroup,
// 释放掉所有资源包括创建的线程
wg.shutdownGracefully();
bg.shutdownGracefully();
}
NioEventLoopGroup
默认线程数为cpu核数*2
private static final int DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt("io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));
protected MultithreadEventLoopGroup(int nThreads, ThreadFactory threadFactory, Object... args) {
super(nThreads == 0 ? DEFAULT_EVENT_LOOP_THREADS : nThreads, threadFactory, args);
}
MultithreadEventExecutorGroup
protected MultithreadEventExecutorGroup(int nThreads, Executor executor, EventExecutorChooserFactory chooserFactory, Object... args) {
this.terminatedChildren = new AtomicInteger();
this.terminationFuture = new DefaultPromise(GlobalEventExecutor.INSTANCE);
if (nThreads <= 0) {
throw new IllegalArgumentException(String.format("nThreads: %d (expected: > 0)", nThreads));
} else {
if (executor == null) {
executor = new ThreadPerTaskExecutor(this.newDefaultThreadFactory());
}
this.children = new EventExecutor[nThreads];
int j;
for(int i = 0; i < nThreads; ++i) {
boolean success = false;
boolean var18 = false;
try {
var18 = true;
this.children[i] = this.newChild((Executor)executor, args);
success = true;
var18 = false;
} catch (Exception var19) {
throw new IllegalStateException("failed to create a child event loop", var19);
} finally {
if (var18) {
if (!success) {
int j;
for(j = 0; j < i; ++j) {
this.children[j].shutdownGracefully();
}
for(j = 0; j < i; ++j) {
EventExecutor e = this.children[j];
try {
while(!e.isTerminated()) {
e.awaitTermination(2147483647L, TimeUnit.SECONDS);
}
} catch (InterruptedException var20) {
Thread.currentThread().interrupt();
break;
}
}
}
}
}
if (!success) {
for(j = 0; j < i; ++j) {
this.children[j].shutdownGracefully();
}
for(j = 0; j < i; ++j) {
EventExecutor e = this.children[j];
try {
while(!e.isTerminated()) {
e.awaitTermination(2147483647L, TimeUnit.SECONDS);
}
} catch (InterruptedException var22) {
Thread.currentThread().interrupt();
break;
}
}
}
}
this.chooser = chooserFactory.newChooser(this.children);
FutureListener<Object> terminationListener = new FutureListener<Object>() {
public void operationComplete(Future<Object> future) throws Exception {
if (MultithreadEventExecutorGroup.this.terminatedChildren.incrementAndGet() == MultithreadEventExecutorGroup.this.children.length) {
MultithreadEventExecutorGroup.this.terminationFuture.setSuccess((Object)null);
}
}
};
EventExecutor[] var24 = this.children;
j = var24.length;
for(int var26 = 0; var26 < j; ++var26) {
EventExecutor e = var24[var26];
e.terminationFuture().addListener(terminationListener);
}
Set<EventExecutor> childrenSet = new LinkedHashSet(this.children.length);
Collections.addAll(childrenSet, this.children);
this.readonlyChildren = Collections.unmodifiableSet(childrenSet);
}
}
1、如果exector是空,创建一个默认的ThreadPreTaskExecutor,使用netty的默认线程工厂
2、根据传入的线程数创建一个(单例)线程池数组
3、循环填充数组中的元素,如果异常,关闭所有单例线程池
4、根据线程池选择工厂创建一个线程选择器
5、为每一个单例线程池添加一个关闭监听器
6、将所有的线程池添加到一个LinkedHashSet
ServerBootstrap
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
private final Map<ChannelOption<?>, Object> childOptions = new ConcurrentHashMap();
private final Map<AttributeKey<?>, Object> childAttrs = new ConcurrentHashMap();
private final ServerBootstrapConfig config = new ServerBootstrapConfig(this);
private volatile EventLoopGroup childGroup;
private volatile ChannelHandler childHandler;
public ServerBootstrap() {
}
ServerBootstrap是一个空的构造器,但有默认成员变量
绑定端口
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = this.initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
} else if (regFuture.isDone()) {
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
final AbstractBootstrap.PendingRegistrationPromise promise = new AbstractBootstrap.PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
promise.setFailure(cause);
} else {
promise.registered();
AbstractBootstrap.doBind0(regFuture, channel, localAddress, promise);
}
}
});
return promise;
}
}
doBind核心是两个方法,initAndRegister和doBind0
final ChannelFuture initAndRegister() {
Channel channel = null;
try {
channel = this.channelFactory.newChannel();
this.init(channel);
} catch (Throwable var3) {
if (channel != null) {
channel.unsafe().closeForcibly();
return (new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE)).setFailure(var3);
}
return (new DefaultChannelPromise(new FailedChannel(), GlobalEventExecutor.INSTANCE)).setFailure(var3);
}
ChannelFuture regFuture = this.config().group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}
return regFuture;
}
channel = this.channelFactory.newChannel();
- 通过Nio的SelectorProvider的openServerSocketChannel方法得到JDK的channel,以供netty包装
- 创建唯一的channelId,创建一个NioMessageUnsafe,用于操作消息,创建一个DefaultChannelPopeLine管道(双向链表)用于过滤所有进出消息
- 创建一个NioServerSocketChannelConfig对象,用于对外展示配置
this.init(channel); 是一个抽象方法,由AbstractBootstrap实现
void init(Channel channel) {
setChannelOptions(channel, (Entry[])this.options0().entrySet().toArray(newOptionArray(0)), logger);
setAttributes(channel, (Entry[])this.attrs0().entrySet().toArray(newAttrArray(0)));
ChannelPipeline p = channel.pipeline();
final EventLoopGroup currentChildGroup = this.childGroup;
final ChannelHandler currentChildHandler = this.childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions = (Entry[])this.childOptions.entrySet().toArray(newOptionArray(0));
final Entry<AttributeKey<?>, Object>[] currentChildAttrs = (Entry[])this.childAttrs.entrySet().toArray(newAttrArray(0));
p.addLast(new ChannelHandler[]{new ChannelInitializer<Channel>() {
public void initChannel(final Channel ch) {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = ServerBootstrap.this.config.handler();
if (handler != null) {
pipeline.addLast(new ChannelHandler[]{handler});
}
ch.eventLoop().execute(new Runnable() {
public void run() {
pipeline.addLast(new ChannelHandler[]{new ServerBootstrap.ServerBootstrapAcceptor(ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)});
}
});
}
}});
}
public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
AbstractChannelHandlerContext newCtx;
synchronized(this) {
checkMultiplicity(handler);
newCtx = this.newContext(group, this.filterName(name, handler), handler);
this.addLast0(newCtx);
if (!this.registered) {
newCtx.setAddPending();
this.callHandlerCallbackLater(newCtx, true);
return this;
}
EventExecutor executor = newCtx.executor();
if (!executor.inEventLoop()) {
this.callHandlerAddedInEventLoop(newCtx, executor);
return this;
}
}
this.callHandlerAdded0(newCtx);
return this;
}
1、检测handler是否标准
2、创建一个AbstractChannelHandlerContext对象,每当channelHandler添加到pipeline都会创建context,它的主要功能是管理它所关联的handler和统一pipeline中其他handler的交互
3、将context添加到链表
4、同步/异步/晚点异步 进行回调
protected void doBind(SocketAddress localAddress) throws Exception {
if (PlatformDependent.javaVersion() >= 7) {
this.javaChannel().bind(localAddress, this.config.getBacklog());
} else {
this.javaChannel().socket().bind(localAddress, this.config.getBacklog());
}
}
调用JavaChannel的绑定方法
public final void bind(SocketAddress localAddress, ChannelPromise promise) {
this.assertEventLoop();
if (promise.setUncancellable() && this.ensureOpen(promise)) {
if (Boolean.TRUE.equals(AbstractChannel.this.config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress() && !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
AbstractChannel.logger.warn("A non-root user can't receive a broadcast packet if the socket is not bound to a wildcard address; binding to a non-wildcard address (" + localAddress + ") anyway as requested.");
}
boolean wasActive = AbstractChannel.this.isActive();
try {
AbstractChannel.this.doBind(localAddress);
} catch (Throwable var5) {
this.safeSetFailure(promise, var5);
this.closeIfClosed();
return;
}
if (!wasActive && AbstractChannel.this.isActive()) {
this.invokeLater(new Runnable() {
public void run() {
AbstractChannel.this.pipeline.fireChannelActive();
}
});
}
this.safeSetSuccess(promise);
}
}
调用到safeSetSuccess,就可以告诉promise任务完成进行监听
protected void run() {
while(true) {
while(true) {
while(true) {
try {
try {
switch(this.selectStrategy.calculateStrategy(this.selectNowSupplier, this.hasTasks())) {
case -3:
case -1:
this.select(this.wakenUp.getAndSet(false));
if (this.wakenUp.get()) {
this.selector.wakeup();
}
break;
case -2:
continue;
}
} catch (IOException var23) {
this.rebuildSelector0();
handleLoopException(var23);
continue;
}
this.cancelledKeys = 0;
this.needsToSelectAgain = false;
int ioRatio = this.ioRatio;
if (ioRatio == 100) {
try {
this.processSelectedKeys();
} finally {
this.runAllTasks();
}
} else {
long ioStartTime = System.nanoTime();
boolean var14 = false;
try {
var14 = true;
this.processSelectedKeys();
var14 = false;
} finally {
if (var14) {
long ioTime = System.nanoTime() - ioStartTime;
this.runAllTasks(ioTime * (long)(100 - ioRatio) / (long)ioRatio);
}
}
long ioTime = System.nanoTime() - ioStartTime;
this.runAllTasks(ioTime * (long)(100 - ioRatio) / (long)ioRatio);
}
} catch (Throwable var24) {
handleLoopException(var24);
}
break;
}
try {
if (this.isShuttingDown()) {
this.closeAll();
if (this.confirmShutdown()) {
return;
}
}
} catch (Throwable var20) {
handleLoopException(var20);
}
}
}
}
到run方法无限循环,服务器端启动