package com.lefu.remote.netty.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import java.util.Arrays; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lefu.remote.netty.EventLoopGroupFactory; /** * {@link ServerBootstrap} 的基础配置类 * <pre> * 任务类继承此类即可方便的实现Netty的服务端。 * </pre> * @author jiang.li * */ public abstract class AbstractServerConfigure implements NettyServer { private final Logger log = LoggerFactory.getLogger(getClass()); protected ServerBootstrap bootstrap; protected NioEventLoopGroup bossGroup; protected NioEventLoopGroup workGroup; protected ChannelInitializer<? extends Channel> channelInitializer; protected Map<Integer, Channel> serverChannels = new Hashtable<Integer, Channel>(); protected LogLevel nettyLogLevel = LogLevel.INFO; private AtomicBoolean isStarted = new AtomicBoolean(false); private AtomicBoolean isShutdown = new AtomicBoolean(false); private int bossGroupSize = Runtime.getRuntime().availableProcessors(); private int workGroupSize = Runtime.getRuntime().availableProcessors() * 4; private boolean bossGroupSetted = false; private boolean workGroupSetted = false; /** * 配置 Parent options 和 Child options * @param bootstrap */ protected abstract void options(ServerBootstrap bootstrap); @Override public void init() throws Exception { if (isStarted.get()) { throw new IllegalStateException("Netty server bootstrap already started!"); } configure(); if (channelInitializer == null) { throw new IllegalStateException("ChannelInitializer is null, unset in configure() ?"); } if (!bossGroupSetted) { bossGroup = EventLoopGroupFactory.newNioLoopGroup(bossGroupSize); } if (!workGroupSetted) { workGroup = EventLoopGroupFactory.newNioLoopGroup(workGroupSize); } bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(nettyLogLevel)) .childHandler(channelInitializer); options(bootstrap); isStarted.set(true); isShutdown.set(false); } @Override public Map<Integer, Channel> bind(int... ports) throws Exception { if (ports == null) { throw new NullPointerException(); } init(); for (int port : ports) { ChannelFuture channelFuture = bootstrap.bind(port); Channel serverChannel = channelFuture.sync().channel(); serverChannels.put(new Integer(port), serverChannel); } log.info(String.format("Netty server started, listen on %1$s with properties -> [BossGroupSize=%2$d,WorkGroupSize=%3$d]", Arrays.toString(ports), bossGroup.executorCount(), workGroup.executorCount())); return serverChannels; } @Override public void destroy() { if (isShutdown.get()) { return; } if (bossGroup != null) { bossGroup.shutdownGracefully(); } if (workGroup != null) { workGroup.shutdownGracefully(); } isShutdown.set(true); isStarted.set(false); bossGroupSetted = false; workGroupSetted = false; serverChannels.clear(); log.info("Netty server bootstrap is going shutdown!"); } public NioEventLoopGroup getBossGroup() { return bossGroup; } public NioEventLoopGroup getWorkGroup() { return workGroup; } public void setBothGroupSize(int bossGroupSize, int workGroupSize) { setBossGroupSize(bossGroupSize); setWorkGroupSize(workGroupSize); } public void setBossGroupSize(int bossGroupSize) { if(bossGroupSize <= 0) { throw new IllegalArgumentException(); } this.bossGroupSize = bossGroupSize; } public void setWorkGroupSize(int workGroupSize) { if (workGroupSize <= 0) { throw new IllegalArgumentException(); } this.workGroupSize = workGroupSize; } public void setBossGroup(NioEventLoopGroup bossGroup) { if (bossGroup != null) { this.bossGroup = bossGroup; this.bossGroupSetted = true; } } public void setWorkGroup(NioEventLoopGroup workGroup) { if (workGroup != null) { this.workGroup = workGroup; this.workGroupSetted = true; } } protected void setChannelInitializer( ChannelInitializer<? extends Channel> channelInitializer) { this.channelInitializer = channelInitializer; } public void setNettyLogLevel(LogLevel nettyLogLevel) { this.nettyLogLevel = nettyLogLevel; } public boolean getIsStarted() { return isStarted.get(); } public boolean getIsShutdown() { return isShutdown.get(); } public ServerBootstrap getBootstrap() { return bootstrap; } }