sailfish.remoting.DefaultServer.java Source code

Java tutorial

Introduction

Here is the source code for sailfish.remoting.DefaultServer.java

Source

/**
 *
 *   Copyright 2016-2016 spccold
 *
 *   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 sailfish.remoting;

import java.util.Collection;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.EventExecutorGroup;
import sailfish.remoting.channel.ExchangeChannelGroup;
import sailfish.remoting.codec.RemotingDecoder;
import sailfish.remoting.codec.RemotingEncoder;
import sailfish.remoting.configuration.ExchangeServerConfig;
import sailfish.remoting.constants.ChannelAttrKeys;
import sailfish.remoting.constants.RemotingConstants;
import sailfish.remoting.eventgroup.ServerEventGroup;
import sailfish.remoting.exceptions.SailfishException;
import sailfish.remoting.handler.DefaultMsgHandler;
import sailfish.remoting.handler.HeartbeatChannelHandler;
import sailfish.remoting.handler.MsgHandler;
import sailfish.remoting.handler.NegotiateChannelHandler;
import sailfish.remoting.handler.ConcreteRequestHandler;
import sailfish.remoting.protocol.Protocol;
import sailfish.remoting.utils.ChannelUtil;
import sailfish.remoting.utils.ParameterChecker;

/**
 * 
 * @author spccold
 * @version $Id: ExchangeServer.java, v 0.1 20161026 ?3:52:19 jileng Exp $
 */
public class DefaultServer implements Server {

    private volatile boolean isClosed = false;
    private final ExchangeServerConfig config;
    private final MsgHandler<Protocol> msgHandler;
    private Channel channel;

    public DefaultServer(ExchangeServerConfig config) {
        this.config = ParameterChecker.checkNotNull(config, "ExchangeServerConfig");
        this.msgHandler = new DefaultMsgHandler(config.getRequestProcessors());
    }

    public void start() throws SailfishException {
        ServerBootstrap boot = newServerBootstrap();
        EventLoopGroup accept = NettyPlatformIndependent.newEventLoopGroup(1,
                new DefaultThreadFactory(RemotingConstants.SERVER_ACCEPT_THREADNAME));
        if (null != config.getEventLoopGroup()) {
            boot.group(accept, config.getEventLoopGroup());
        } else {
            boot.group(accept, ServerEventGroup.INSTANCE.getLoopGroup());
        }
        final EventExecutorGroup executor = (null != config.getEventExecutorGroup() ? config.getEventExecutorGroup()
                : ServerEventGroup.INSTANCE.getExecutorGroup());
        boot.localAddress(config.address().host(), config.address().port());
        boot.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                ch.attr(ChannelAttrKeys.OneTime.idleTimeout).set(config.idleTimeout());
                ch.attr(ChannelAttrKeys.maxIdleTimeout).set(config.maxIdleTimeout());
                ch.attr(ChannelAttrKeys.exchangeServer).set(DefaultServer.this);
                pipeline.addLast(executor, RemotingEncoder.INSTANCE, new RemotingDecoder(),
                        new IdleStateHandler(config.idleTimeout(), 0, 0), HeartbeatChannelHandler.INSTANCE,
                        NegotiateChannelHandler.INSTANCE, ConcreteRequestHandler.INSTANCE);
            }
        });
        try {
            channel = boot.bind().syncUninterruptibly().channel();
        } catch (Throwable cause) {
            throw new SailfishException(cause);
        }
    }

    private ServerBootstrap newServerBootstrap() {
        ServerBootstrap serverBoot = new ServerBootstrap();
        serverBoot.channel(NettyPlatformIndependent.serverChannelClass());
        // connections wait for accept
        serverBoot.option(ChannelOption.SO_BACKLOG, 1024);
        serverBoot.option(ChannelOption.SO_REUSEADDR, true);
        // replace by heart beat
        serverBoot.childOption(ChannelOption.SO_KEEPALIVE, false);
        serverBoot.childOption(ChannelOption.TCP_NODELAY, true);
        serverBoot.childOption(ChannelOption.SO_SNDBUF, 32 * 1024);
        serverBoot.childOption(ChannelOption.SO_RCVBUF, 32 * 1024);
        // temporary settings, need more tests
        serverBoot.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK,
                new WriteBufferWaterMark(8 * 1024, 32 * 1024));
        serverBoot.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        //default is true, reduce thread context switching
        serverBoot.childOption(ChannelOption.SINGLE_EVENTEXECUTOR_PER_GROUP, true);
        return serverBoot;
    }

    @Override
    public void close() {
        close(0);
    }

    @Override
    public void close(int timeout) {
        if (isClosed()) {
            return;
        }
        synchronized (this) {
            if (isClosed())
                return;
            ChannelUtil.closeChannel(channel);
        }
    }

    @Override
    public boolean isClosed() {
        return this.isClosed;
    }

    public MsgHandler<Protocol> getMsgHandler() {
        return msgHandler;
    }

    @Override
    public Collection<ExchangeChannelGroup> listChannelGroups() {
        return NegotiateChannelHandler.uuid2ChannelGroup.values();
    }
}