io.mycat.netty.NettyServer.java Source code

Java tutorial

Introduction

Here is the source code for io.mycat.netty.NettyServer.java

Source

/*
 * Copyright 2014-2016 the original author or authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS? BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.mycat.netty;

import io.mycat.netty.conf.Configuration;
import io.mycat.netty.util.ExtendableThreadPoolExecutor;
import io.mycat.netty.util.Threads;
import io.mycat.netty.util.SysProperties;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Properties;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public abstract class NettyServer {

    private static Logger logger = LoggerFactory.getLogger(NettyServer.class);

    /**
     * The default port to use for the server.
     */
    public static final int DEFAULT_LISTEN_PORT = 6100;

    private ServerArgs args;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private ThreadPoolExecutor userExecutor;
    private ChannelFuture f;

    public NettyServer(ServerArgs args) {
        this.args = args;
    }

    /**
     * Listen for incoming connections.
     */
    public void init() {

        logger.info("nettyServer init");
        try {
            Configuration.init();
        } catch (Exception e) {
            logger.error("Exception happen when init ddal-engine ", e);
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * Listen for incoming connections.
     */
    public void listen() {
        logger.info("{} server is starting", getServerName());
        args.validate();
        ServerBootstrap b = configServer();
        try {
            // start server
            f = b.bind(args.port).sync();
            logger.info("{} server started and listening on {}", getServerName(), args.port);
            // register shutown hook
            Runtime.getRuntime().addShutdownHook(new ShutdownThread());
        } catch (Exception e) {
            logger.error("Exception happen when start " + getServerName(), e);
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new RuntimeException(e);
        }
    }

    /**
     * blocking to wait for close.
     */
    public void waitForClose() throws InterruptedException {
        f.channel().closeFuture().sync();
    }

    public void stop() {
        logger.info("{} server is stopping", getServerName());
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
        int timeoutMills = args.shutdownTimeoutMills;
        Threads.shutdownGracefully(userExecutor, timeoutMills, timeoutMills, TimeUnit.SECONDS);
        logger.info("{} server stoped", getServerName());
    }

    private ServerBootstrap configServer() {
        bossGroup = new NioEventLoopGroup(args.bossThreads, new DefaultThreadFactory("NettyBossGroup", true));
        workerGroup = new NioEventLoopGroup(args.workerThreads, new DefaultThreadFactory("NettyWorkerGroup", true));
        userExecutor = createUserThreadExecutor();

        final ProtocolHandler handshakeHandler = newHandshakeHandler(userExecutor);
        final ProtocolHandler protocolHandler = newProtocolHandler(userExecutor);

        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .childOption(ChannelOption.SO_REUSEADDR, true).childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.TCP_NODELAY, true);

        if (args.socketTimeoutMills > 0) {
            b.childOption(ChannelOption.SO_TIMEOUT, args.socketTimeoutMills);
        }

        if (args.recvBuff > 0) {
            b.childOption(ChannelOption.SO_RCVBUF, args.recvBuff);
        }

        if (args.sendBuff > 0) {
            b.childOption(ChannelOption.SO_SNDBUF, args.sendBuff);
        }

        b.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(createProtocolDecoder(), /* createProtocolEncoder(), */ handshakeHandler,
                        protocolHandler);
            }
        });

        return b;
    }

    public ThreadPoolExecutor createUserThreadExecutor() {
        ExtendableThreadPoolExecutor.TaskQueue queue = new ExtendableThreadPoolExecutor.TaskQueue(
                SysProperties.THREAD_QUEUE_SIZE);
        int poolCoreSize = SysProperties.THREAD_POOL_SIZE_CORE;
        int poolMaxSize = SysProperties.THREAD_POOL_SIZE_MAX;
        poolMaxSize = poolMaxSize > poolCoreSize ? poolMaxSize : poolCoreSize;
        ExtendableThreadPoolExecutor userExecutor = new ExtendableThreadPoolExecutor(poolCoreSize, poolMaxSize, 5L,
                TimeUnit.MINUTES, queue, Threads.newThreadFactory("request-processor"));
        return userExecutor;
    }

    private ProtocolHandler newHandshakeHandler(ThreadPoolExecutor userExecutor) {
        ProtocolHandler handshakeHandler = createHandshakeHandler();
        handshakeHandler.setUserExecutor(userExecutor);
        return handshakeHandler;
    }

    private ProtocolHandler newProtocolHandler(ThreadPoolExecutor userExecutor) {
        ProtocolHandler protocolHandler = createProtocolHandler();
        protocolHandler.setUserExecutor(userExecutor);
        return protocolHandler;
    }

    protected abstract String getServerName();

    protected abstract ChannelHandler createProtocolDecoder();

    protected abstract ProtocolHandler createHandshakeHandler();

    protected abstract ProtocolHandler createProtocolHandler();

    class ShutdownThread extends Thread {
        @Override
        public void run() {
            NettyServer.this.stop();
        }
    }
}