sailfish.remoting.channel.AbstractConfigurableExchangeChannelGroup.java Source code

Java tutorial

Introduction

Here is the source code for sailfish.remoting.channel.AbstractConfigurableExchangeChannelGroup.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.channel;

import java.util.UUID;
import java.util.concurrent.CountDownLatch;

import static sailfish.remoting.constants.ChannelAttrKeys.OneTime;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
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.EventExecutorGroup;
import sailfish.remoting.Address;
import sailfish.remoting.NettyPlatformIndependent;
import sailfish.remoting.codec.RemotingDecoder;
import sailfish.remoting.codec.RemotingEncoder;
import sailfish.remoting.configuration.NegotiateConfig;
import sailfish.remoting.constants.ChannelAttrKeys;
import sailfish.remoting.eventgroup.ClientEventGroup;
import sailfish.remoting.handler.HeartbeatChannelHandler;
import sailfish.remoting.handler.NegotiateChannelHandler;
import sailfish.remoting.handler.ConcreteRequestHandler;

/**
 * @author spccold
 * @version $Id: AbstractConfigurableExchangeChannelGroup.java, v 0.1 20161123 ?3:47:32 spccold
 *          Exp $
 */
public abstract class AbstractConfigurableExchangeChannelGroup extends AbstractExchangeChannelGroup {

    protected AbstractConfigurableExchangeChannelGroup() {
        super(UUID.randomUUID());
    }

    protected Bootstrap configureBoostrap(Address remoteAddress, int connectTimeout, NegotiateConfig config,
            ExchangeChannelGroup channelGroup, EventLoopGroup loopGroup, EventExecutorGroup executorGroup) {
        Bootstrap boot = newBootstrap();
        if (null == loopGroup) {
            loopGroup = ClientEventGroup.INSTANCE.getLoopGroup();
        }
        if (null == executorGroup) {
            executorGroup = ClientEventGroup.INSTANCE.getExecutorGroup();
        }
        boot.group(loopGroup);
        boot.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout);
        boot.remoteAddress(remoteAddress.host(), remoteAddress.port());
        boot.handler(newChannelInitializer(config, channelGroup, executorGroup));
        return boot;
    }

    private Bootstrap newBootstrap() {
        Bootstrap boot = new Bootstrap();
        boot.channel(NettyPlatformIndependent.channelClass());
        boot.option(ChannelOption.TCP_NODELAY, true);
        // replace by heart beat
        boot.option(ChannelOption.SO_KEEPALIVE, false);
        // default is pooled direct
        // ByteBuf(io.netty.util.internal.PlatformDependent.DIRECT_BUFFER_PREFERRED)
        boot.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
        // 32kb(for massive long connections, See
        // http://www.infoq.com/cn/articles/netty-million-level-push-service-design-points)
        // 64kb(RocketMq remoting default value)
        boot.option(ChannelOption.SO_SNDBUF, 32 * 1024);
        boot.option(ChannelOption.SO_RCVBUF, 32 * 1024);
        // temporary settings, need more tests
        boot.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(8 * 1024, 32 * 1024));
        //default is true, reduce thread context switching
        boot.option(ChannelOption.SINGLE_EVENTEXECUTOR_PER_GROUP, true);
        return boot;
    }

    private ChannelInitializer<SocketChannel> newChannelInitializer(final NegotiateConfig config,
            final ExchangeChannelGroup channelGroup, final EventExecutorGroup executorGroup) {
        return new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline pipeline = ch.pipeline();
                ch.attr(ChannelAttrKeys.maxIdleTimeout).set(config.maxIdleTimeout());
                ch.attr(ChannelAttrKeys.channelGroup).set(channelGroup);
                ch.attr(ChannelAttrKeys.clientSide).set(true);
                ch.attr(OneTime.awaitNegotiate).set(new CountDownLatch(1));
                ch.attr(OneTime.channelConfig).set(config);
                // TODO should increase ioRatio when every ChannelHandler bind to executorGroup?
                pipeline.addLast(executorGroup, RemotingEncoder.INSTANCE, new RemotingDecoder(),
                        new IdleStateHandler(config.idleTimeout(), 0, 0), HeartbeatChannelHandler.INSTANCE,
                        NegotiateChannelHandler.INSTANCE, ConcreteRequestHandler.INSTANCE);
            }
        };
    }
}