Redisson關於netty使用的部分源碼分析

1、首先寫個測試類,方便進入查看源碼

package com.redisson;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

/**
 * @Description TODO
 * @Date 2020/6/30 10:29
 * @Author zsj
 */
public class RedissonTest {
    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://192.168.2.41:6379")
        .setPassword("rabbit123@");
        RedissonClient redisson = Redisson.create(config);
        redisson.shutdown();
    }
}

2、進入到Redisson這個類,查看其構造函數

   protected Redisson(Config config) {
        this.config = config;
        Config configCopy = new Config(config);
        // 繼續查看源碼
        this.connectionManager = ConfigSupport.createConnectionManager(configCopy);
        this.evictionScheduler = new EvictionScheduler(this.connectionManager.getCommandExecutor());
        this.writeBehindService = new WriteBehindService(this.connectionManager.getCommandExecutor());
    }

3、進入到 MasterSlaveConnectionManager類

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.redisson.connection;

import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.kqueue.KQueueDatagramChannel;
import io.netty.channel.kqueue.KQueueEventLoopGroup;
import io.netty.channel.kqueue.KQueueSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.resolver.AddressResolverGroup;
import io.netty.resolver.DefaultAddressResolverGroup;
import io.netty.resolver.dns.DnsServerAddressStreamProviders;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.ImmediateEventExecutor;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.PlatformDependent;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.redisson.ElementsSubscribeService;
import org.redisson.Version;
import org.redisson.api.NodeType;
import org.redisson.api.RFuture;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisClientConfig;
import org.redisson.client.RedisConnection;
import org.redisson.client.RedisException;
import org.redisson.client.RedisNodeNotFoundException;
import org.redisson.client.codec.Codec;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.cluster.ClusterSlotRange;
import org.redisson.command.CommandSyncService;
import org.redisson.config.BaseMasterSlaveServersConfig;
import org.redisson.config.Config;
import org.redisson.config.MasterSlaveServersConfig;
import org.redisson.config.TransportMode;
import org.redisson.misc.CountableListener;
import org.redisson.misc.InfinitySemaphoreLatch;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedisURI;
import org.redisson.misc.RedissonPromise;
import org.redisson.pubsub.PublishSubscribeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MasterSlaveConnectionManager implements ConnectionManager {
    public static final Timeout DUMMY_TIMEOUT = new Timeout() {
        public Timer timer() {
            return null;
        }

        public TimerTask task() {
            return null;
        }

        public boolean isExpired() {
            return false;
        }

        public boolean isCancelled() {
            return false;
        }

        public boolean cancel() {
            return true;
        }
    };
    protected final String id;
    public static final int MAX_SLOT = 16384;
    protected final ClusterSlotRange singleSlotRange;
    private final Logger log;
    private HashedWheelTimer timer;
   //redisson序列化協議
    protected Codec codec;

    // netty客戶端連接服務端的EventLoopGroup
    protected final EventLoopGroup group;
    //netty客戶端連接服務端的channelClass 根據傳輸方式而定
    protected final Class<? extends SocketChannel> socketChannelClass;
    protected DNSMonitor dnsMonitor;
    protected MasterSlaveServersConfig config;
    private final AtomicReferenceArray<MasterSlaveEntry> slot2entry;
    private final Map<RedisClient, MasterSlaveEntry> client2entry;
    private final Promise<Void> shutdownPromise;
    private final InfinitySemaphoreLatch shutdownLatch;
    private IdleConnectionWatcher connectionWatcher;
    private final ConnectionEventsHub connectionEventsHub;
    private final ExecutorService executor;
    private final CommandSyncService commandExecutor;
    private final Config cfg;
    protected final AddressResolverGroup<InetSocketAddress> resolverGroup;
    private final ElementsSubscribeService elementsSubscribeService;
    private PublishSubscribeService subscribeService;
    private final Map<Object, RedisConnection> nodeConnections;

    public MasterSlaveConnectionManager(MasterSlaveServersConfig cfg, Config config, UUID id) {
        this(config, id);
        this.config = cfg;
        this.initTimer(cfg);
        this.initSingleEntry();
    }

    protected MasterSlaveConnectionManager(Config cfg, UUID id) {
        this.singleSlotRange = new ClusterSlotRange(0, 16383);
        this.log = LoggerFactory.getLogger(this.getClass());
        this.slot2entry = new AtomicReferenceArray(16384);
        this.client2entry = new ConcurrentHashMap();
        this.shutdownPromise = ImmediateEventExecutor.INSTANCE.newPromise();
        this.shutdownLatch = new InfinitySemaphoreLatch();
        this.connectionEventsHub = new ConnectionEventsHub();
        this.elementsSubscribeService = new ElementsSubscribeService(this);
        this.nodeConnections = new ConcurrentHashMap();
        this.id = id.toString();
        Version.logVersion();
        if (cfg.getTransportMode() == TransportMode.EPOLL) {
                //傳輸方式 epoll
            if (cfg.getEventLoopGroup() == null) {
                this.group = new EpollEventLoopGroup(cfg.getNettyThreads(), new DefaultThreadFactory("redisson-netty"));
            } else {
                this.group = cfg.getEventLoopGroup();
            }
           // 對應傳輸方式epoll的SocketChannel
            this.socketChannelClass = EpollSocketChannel.class;
            if (PlatformDependent.isAndroid()) {
                this.resolverGroup = DefaultAddressResolverGroup.INSTANCE;
            } else {
                this.resolverGroup = cfg.getAddressResolverGroupFactory().create(EpollDatagramChannel.class, DnsServerAddressStreamProviders.platformDefault());
            }
        } else if (cfg.getTransportMode() == TransportMode.KQUEUE) {
             //傳輸方式 kqueue
            if (cfg.getEventLoopGroup() == null) {
                this.group = new KQueueEventLoopGroup(cfg.getNettyThreads(), new DefaultThreadFactory("redisson-netty"));
            } else {
                this.group = cfg.getEventLoopGroup();
            }
   // 對應傳輸方式kqueue的SocketChannel
            this.socketChannelClass = KQueueSocketChannel.class;
            if (PlatformDependent.isAndroid()) {
                this.resolverGroup = DefaultAddressResolverGroup.INSTANCE;
            } else {
                this.resolverGroup = cfg.getAddressResolverGroupFactory().create(KQueueDatagramChannel.class, DnsServerAddressStreamProviders.platformDefault());
            }
        } else {
         //默認 nio傳輸方式
            if (cfg.getEventLoopGroup() == null) {
                this.group = new NioEventLoopGroup(cfg.getNettyThreads(), new DefaultThreadFactory("redisson-netty"));
            } else {
                this.group = cfg.getEventLoopGroup();
            }
       // 對應傳輸方式nio的SocketChannel
            this.socketChannelClass = NioSocketChannel.class;
            if (PlatformDependent.isAndroid()) {
                this.resolverGroup = DefaultAddressResolverGroup.INSTANCE;
            } else {
                this.resolverGroup = cfg.getAddressResolverGroupFactory().create(NioDatagramChannel.class, DnsServerAddressStreamProviders.platformDefault());
            }
        }

        if (cfg.getExecutor() == null) {
            int threads = Runtime.getRuntime().availableProcessors() * 2;
            if (cfg.getThreads() != 0) {
                threads = cfg.getThreads();
            }

            this.executor = Executors.newFixedThreadPool(threads, new DefaultThreadFactory("redisson"));
        } else {
            this.executor = cfg.getExecutor();
        }

        this.cfg = cfg;
        this.codec = cfg.getCodec();
        this.commandExecutor = new CommandSyncService(this);
    }

    protected void closeNodeConnections() {
        List<RFuture<Void>> futures = new ArrayList();
        Iterator var2 = this.nodeConnections.values().iterator();

        while(var2.hasNext()) {
            RedisConnection connection = (RedisConnection)var2.next();
            RFuture<Void> future = connection.getRedisClient().shutdownAsync();
            futures.add(future);
        }

        var2 = futures.iterator();

        while(var2.hasNext()) {
            RFuture<Void> future = (RFuture)var2.next();
            future.syncUninterruptibly();
        }

    }

    protected void closeNodeConnection(RedisConnection conn) {
        if (this.nodeConnections.values().remove(conn)) {
            conn.closeAsync();
        }

    }

    protected final void disconnectNode(RedisURI addr) {
        RedisConnection conn = (RedisConnection)this.nodeConnections.remove(addr);
        if (conn != null) {
            conn.closeAsync();
        }

    }

    protected final void disconnectNode(RedisClient client) {
        RedisConnection conn = (RedisConnection)this.nodeConnections.remove(client);
        if (conn != null) {
            conn.closeAsync();
        }

    }

    protected final RFuture<RedisConnection> connectToNode(BaseMasterSlaveServersConfig<?> cfg, RedisURI addr, RedisClient client, String sslHostname) {
        Object key;
        if (client != null) {
            key = client;
        } else {
            key = addr;
        }

        RedisConnection conn = (RedisConnection)this.nodeConnections.get(key);
        if (conn != null) {
            if (conn.isActive()) {
                return RedissonPromise.newSucceededFuture(conn);
            }

            this.nodeConnections.remove(key);
            conn.closeAsync();
        }

        if (addr != null) {
            client = this.createClient(NodeType.MASTER, addr, cfg.getConnectTimeout(), cfg.getTimeout(), sslHostname);
        }

        RPromise<RedisConnection> result = new RedissonPromise();
        RFuture<RedisConnection> future = client.connectAsync();
        future.onComplete((connection, e) -> {
            if (e != null) {
                result.tryFailure(e);
            } else {
                if (connection.isActive()) {
                    this.nodeConnections.put(key, connection);
                    result.trySuccess(connection);
                } else {
                    connection.closeAsync();
                    result.tryFailure(new RedisException("Connection to " + connection.getRedisClient().getAddr() + " is not active!"));
                }

            }
        });
        return result;
    }

    public String getId() {
        return this.id;
    }

    public boolean isClusterMode() {
        return false;
    }

    public CommandSyncService getCommandExecutor() {
        return this.commandExecutor;
    }

    public IdleConnectionWatcher getConnectionWatcher() {
        return this.connectionWatcher;
    }

    public Config getCfg() {
        return this.cfg;
    }

    public MasterSlaveServersConfig getConfig() {
        return this.config;
    }

    public Codec getCodec() {
        return this.codec;
    }

    public Collection<MasterSlaveEntry> getEntrySet() {
        return this.client2entry.values();
    }

    protected void initTimer(MasterSlaveServersConfig config) {
        int[] timeouts = new int[]{config.getRetryInterval(), config.getTimeout()};
        Arrays.sort(timeouts);
        int minTimeout = timeouts[0];
        if (minTimeout % 100 != 0) {
            minTimeout = minTimeout % 100 / 2;
        } else if (minTimeout == 100) {
            minTimeout = 50;
        } else {
            minTimeout = 100;
        }

        this.timer = new HashedWheelTimer(new DefaultThreadFactory("redisson-timer"), (long)minTimeout, TimeUnit.MILLISECONDS, 1024, false);
        this.connectionWatcher = new IdleConnectionWatcher(this, config);
        this.subscribeService = new PublishSubscribeService(this, config);
    }

    protected void initSingleEntry() {
        try {
            Object entry;
            if (this.config.checkSkipSlavesInit()) {
                entry = new SingleEntry(this, this.config);
            } else {
                entry = this.createMasterSlaveEntry(this.config);
            }

            RFuture<RedisClient> f = ((MasterSlaveEntry)entry).setupMasterEntry(new RedisURI(this.config.getMasterAddress()));
//客戶端異步連接
            f.syncUninterruptibly();

            for(int slot = this.singleSlotRange.getStartSlot(); slot < this.singleSlotRange.getEndSlot() + 1; ++slot) {
                this.addEntry(slot, (MasterSlaveEntry)entry);
            }

            this.startDNSMonitoring((RedisClient)f.getNow());
        } catch (Exception var4) {
            this.stopThreads();
            throw var4;
        }
    }

    protected void startDNSMonitoring(RedisClient masterHost) {
        if (this.config.getDnsMonitoringInterval() != -1L) {
            Set<RedisURI> slaveAddresses = (Set)this.config.getSlaveAddresses().stream().map((r) -> {
                return new RedisURI(r);
            }).collect(Collectors.toSet());
            this.dnsMonitor = new DNSMonitor(this, masterHost, slaveAddresses, this.config.getDnsMonitoringInterval(), this.resolverGroup);
            this.dnsMonitor.start();
        }

    }

    protected MasterSlaveEntry createMasterSlaveEntry(MasterSlaveServersConfig config) {
        MasterSlaveEntry entry = new MasterSlaveEntry(this, config);
        List<RFuture<Void>> fs = entry.initSlaveBalancer(Collections.emptySet());
        Iterator var4 = fs.iterator();

        while(var4.hasNext()) {
            RFuture<Void> future = (RFuture)var4.next();
            future.syncUninterruptibly();
        }

        return entry;
    }

    protected MasterSlaveServersConfig create(BaseMasterSlaveServersConfig<?> cfg) {
        MasterSlaveServersConfig c = new MasterSlaveServersConfig();
        c.setPingConnectionInterval(cfg.getPingConnectionInterval());
        c.setSslEnableEndpointIdentification(cfg.isSslEnableEndpointIdentification());
        c.setSslProvider(cfg.getSslProvider());
        c.setSslTruststore(cfg.getSslTruststore());
        c.setSslTruststorePassword(cfg.getSslTruststorePassword());
        c.setSslKeystore(cfg.getSslKeystore());
        c.setSslKeystorePassword(cfg.getSslKeystorePassword());
        c.setRetryInterval(cfg.getRetryInterval());
        c.setRetryAttempts(cfg.getRetryAttempts());
        c.setTimeout(cfg.getTimeout());
        c.setLoadBalancer(cfg.getLoadBalancer());
        c.setPassword(cfg.getPassword());
        c.setUsername(cfg.getUsername());
        c.setClientName(cfg.getClientName());
        c.setMasterConnectionPoolSize(cfg.getMasterConnectionPoolSize());
        c.setSlaveConnectionPoolSize(cfg.getSlaveConnectionPoolSize());
        c.setSubscriptionConnectionPoolSize(cfg.getSubscriptionConnectionPoolSize());
        c.setSubscriptionsPerConnection(cfg.getSubscriptionsPerConnection());
        c.setConnectTimeout(cfg.getConnectTimeout());
        c.setIdleConnectionTimeout(cfg.getIdleConnectionTimeout());
        c.setFailedSlaveCheckInterval(cfg.getFailedSlaveCheckInterval());
        c.setFailedSlaveReconnectionInterval(cfg.getFailedSlaveReconnectionInterval());
        c.setMasterConnectionMinimumIdleSize(cfg.getMasterConnectionMinimumIdleSize());
        c.setSlaveConnectionMinimumIdleSize(cfg.getSlaveConnectionMinimumIdleSize());
        c.setSubscriptionConnectionMinimumIdleSize(cfg.getSubscriptionConnectionMinimumIdleSize());
        c.setReadMode(cfg.getReadMode());
        c.setSubscriptionMode(cfg.getSubscriptionMode());
        c.setDnsMonitoringInterval(cfg.getDnsMonitoringInterval());
        c.setKeepAlive(cfg.isKeepAlive());
        return c;
    }

    public RedisClient createClient(NodeType type, RedisURI address, String sslHostname) {
        RedisClient client = this.createClient(type, address, this.config.getConnectTimeout(), this.config.getTimeout(), sslHostname);
        return client;
    }

    public RedisClient createClient(NodeType type, InetSocketAddress address, RedisURI uri, String sslHostname) {
        RedisClient client = this.createClient(type, address, uri, this.config.getConnectTimeout(), this.config.getTimeout(), sslHostname);
        return client;
    }

    public RedisClient createClient(NodeType type, RedisURI address, int timeout, int commandTimeout, String sslHostname) {
        RedisClientConfig redisConfig = this.createRedisConfig(type, address, timeout, commandTimeout, sslHostname);
        return RedisClient.create(redisConfig);
    }

    private RedisClient createClient(NodeType type, InetSocketAddress address, RedisURI uri, int timeout, int commandTimeout, String sslHostname) {
        RedisClientConfig redisConfig = this.createRedisConfig(type, (RedisURI)null, timeout, commandTimeout, sslHostname);
        redisConfig.setAddress(address, uri);
        return RedisClient.create(redisConfig);
    }

    protected RedisClientConfig createRedisConfig(NodeType type, RedisURI address, int timeout, int commandTimeout, String sslHostname) {
        RedisClientConfig redisConfig = new RedisClientConfig();
        redisConfig.setAddress(address).setTimer(this.timer).setExecutor(this.executor).setResolverGroup(this.resolverGroup).setGroup(this.group).setSocketChannelClass(this.socketChannelClass).setConnectTimeout(timeout).setCommandTimeout(commandTimeout).setSslHostname(sslHostname).setSslEnableEndpointIdentification(this.config.isSslEnableEndpointIdentification()).setSslProvider(this.config.getSslProvider()).setSslTruststore(this.config.getSslTruststore()).setSslTruststorePassword(this.config.getSslTruststorePassword()).setSslKeystore(this.config.getSslKeystore()).setSslKeystorePassword(this.config.getSslKeystorePassword()).setClientName(this.config.getClientName()).setDecodeInExecutor(this.cfg.isDecodeInExecutor()).setKeepPubSubOrder(this.cfg.isKeepPubSubOrder()).setPingConnectionInterval(this.config.getPingConnectionInterval()).setKeepAlive(this.config.isKeepAlive()).setTcpNoDelay(this.config.isTcpNoDelay()).setUsername(this.config.getUsername()).setPassword(this.config.getPassword()).setNettyHook(this.cfg.getNettyHook());
        if (type != NodeType.SENTINEL) {
            redisConfig.setDatabase(this.config.getDatabase());
        }

        return redisConfig;
    }

    public int calcSlot(String key) {
        return this.singleSlotRange.getStartSlot();
    }

    public int calcSlot(byte[] key) {
        return this.singleSlotRange.getStartSlot();
    }

    public MasterSlaveEntry getEntry(InetSocketAddress address) {
        Iterator var2 = this.client2entry.values().iterator();

        MasterSlaveEntry entry;
        InetSocketAddress addr;
        do {
            if (!var2.hasNext()) {
                return null;
            }

            entry = (MasterSlaveEntry)var2.next();
            addr = entry.getClient().getAddr();
        } while(!addr.getAddress().equals(address.getAddress()) || addr.getPort() != address.getPort());

        return entry;
    }

    protected MasterSlaveEntry getEntry(RedisURI addr) {
        Iterator var2 = this.client2entry.values().iterator();

        MasterSlaveEntry entry;
        do {
            if (!var2.hasNext()) {
                return null;
            }

            entry = (MasterSlaveEntry)var2.next();
            if (RedisURI.compare(entry.getClient().getAddr(), addr)) {
                return entry;
            }
        } while(!entry.hasSlave(addr));

        return entry;
    }

    public MasterSlaveEntry getEntry(RedisClient redisClient) {
        MasterSlaveEntry entry = (MasterSlaveEntry)this.client2entry.get(redisClient);
        if (entry != null) {
            return entry;
        } else {
            Iterator var3 = this.client2entry.values().iterator();

            MasterSlaveEntry mentry;
            do {
                if (!var3.hasNext()) {
                    return null;
                }

                mentry = (MasterSlaveEntry)var3.next();
            } while(!mentry.hasSlave(redisClient));

            return mentry;
        }
    }

    public MasterSlaveEntry getEntry(String name) {
        int slot = this.calcSlot(name);
        return this.getEntry(slot);
    }

    public MasterSlaveEntry getEntry(int slot) {
        return (MasterSlaveEntry)this.slot2entry.get(slot);
    }

    protected final RFuture<RedisClient> changeMaster(int slot, RedisURI address) {
        MasterSlaveEntry entry = this.getEntry(slot);
        RedisClient oldClient = entry.getClient();
        RFuture<RedisClient> future = entry.changeMaster(address);
        future.onComplete((res, e) -> {
            if (e == null) {
                this.client2entry.remove(oldClient);
                this.client2entry.put(entry.getClient(), entry);
            }

        });
        return future;
    }

    protected final void addEntry(Integer slot, MasterSlaveEntry entry) {
        MasterSlaveEntry oldEntry = (MasterSlaveEntry)this.slot2entry.getAndSet(slot, entry);
        if (oldEntry != entry) {
            entry.incReference();
            this.shutdownEntry(oldEntry);
        }

        this.client2entry.put(entry.getClient(), entry);
    }

    protected final void removeEntry(Integer slot) {
        MasterSlaveEntry entry = (MasterSlaveEntry)this.slot2entry.getAndSet(slot, (Object)null);
        this.shutdownEntry(entry);
    }

    private void shutdownEntry(MasterSlaveEntry entry) {
        if (entry != null && entry.decReference() == 0) {
            this.client2entry.remove(entry.getClient());
            entry.getAllEntries().forEach((e) -> {
                entry.nodeDown(e);
            });
            entry.masterDown();
            entry.shutdownAsync();
            String slaves = (String)entry.getAllEntries().stream().filter((e) -> {
                return !e.getClient().getAddr().equals(entry.getClient().getAddr());
            }).map((e) -> {
                return e.getClient().toString();
            }).collect(Collectors.joining(","));
            this.log.info("{} master and related slaves: {} removed", entry.getClient().getAddr(), slaves);
        }

    }

    public RFuture<RedisConnection> connectionWriteOp(NodeSource source, RedisCommand<?> command) {
        MasterSlaveEntry entry = this.getEntry(source);
        if (entry == null) {
            return this.createNodeNotFoundFuture(source);
        } else {
            return source.getRedirect() != null && !RedisURI.compare(entry.getClient().getAddr(), source.getAddr()) && entry.hasSlave(source.getAddr()) ? entry.redirectedConnectionWriteOp(command, source.getAddr()) : entry.connectionWriteOp(command);
        }
    }

    private MasterSlaveEntry getEntry(NodeSource source) {
        if (source.getRedirect() != null) {
            return this.getEntry(source.getAddr());
        } else {
            MasterSlaveEntry entry = source.getEntry();
            if (source.getRedisClient() != null) {
                entry = this.getEntry(source.getRedisClient());
            }

            if (entry == null && source.getSlot() != null) {
                entry = this.getEntry(source.getSlot());
            }

            return entry;
        }
    }

    public RFuture<RedisConnection> connectionReadOp(NodeSource source, RedisCommand<?> command) {
        MasterSlaveEntry entry = this.getEntry(source);
        if (entry == null) {
            return this.createNodeNotFoundFuture(source);
        } else if (source.getRedirect() != null) {
            return entry.connectionReadOp(command, source.getAddr());
        } else {
            return source.getRedisClient() != null ? entry.connectionReadOp(command, source.getRedisClient()) : entry.connectionReadOp(command);
        }
    }

    protected RFuture<RedisConnection> createNodeNotFoundFuture(NodeSource source) {
        RedisNodeNotFoundException ex;
        if (source.getSlot() != null && source.getAddr() == null && source.getRedisClient() == null) {
            ex = new RedisNodeNotFoundException("Node for slot: " + source.getSlot() + " hasn't been discovered yet. Check cluster slots coverage using CLUSTER NODES command. Increase value of retryAttempts and/or retryInterval settings.");
        } else {
            ex = new RedisNodeNotFoundException("Node: " + source + " hasn't been discovered yet. Increase value of retryAttempts and/or retryInterval settings.");
        }

        return RedissonPromise.newFailedFuture(ex);
    }

    public void releaseWrite(NodeSource source, RedisConnection connection) {
        MasterSlaveEntry entry = this.getEntry(source);
        if (entry == null) {
            this.log.error("Node: " + source + " can't be found");
        } else {
            entry.releaseWrite(connection);
        }

    }

    public void releaseRead(NodeSource source, RedisConnection connection) {
        MasterSlaveEntry entry = this.getEntry(source);
        if (entry == null) {
            this.log.error("Node: " + source + " can't be found");
        } else {
            entry.releaseRead(connection);
        }

    }

    public void shutdown() {
        this.shutdown(0L, 2L, TimeUnit.SECONDS);
    }

    public void shutdown(long quietPeriod, long timeout, TimeUnit unit) {
        if (this.dnsMonitor != null) {
            this.dnsMonitor.stop();
        }

        this.connectionWatcher.stop();
        RPromise<Void> result = new RedissonPromise();
        CountableListener<Void> listener = new CountableListener(result, (Object)null, this.getEntrySet().size());
        Iterator var8 = this.getEntrySet().iterator();

        while(var8.hasNext()) {
            MasterSlaveEntry entry = (MasterSlaveEntry)var8.next();
            entry.shutdownAsync().onComplete(listener);
        }

        result.awaitUninterruptibly(timeout, unit);
        this.resolverGroup.close();
        this.shutdownLatch.close();
        if (this.cfg.getExecutor() == null) {
            this.executor.shutdown();

            try {
                this.executor.awaitTermination(timeout, unit);
            } catch (InterruptedException var10) {
                Thread.currentThread().interrupt();
            }
        }

        this.shutdownPromise.trySuccess((Object)null);
        this.shutdownLatch.awaitUninterruptibly();
        if (this.cfg.getEventLoopGroup() == null) {
            this.group.shutdownGracefully(quietPeriod, timeout, unit).syncUninterruptibly();
        }

        this.timer.stop();
    }

    public boolean isShuttingDown() {
        return this.shutdownLatch.isClosed();
    }

    public boolean isShutdown() {
        return this.group.isTerminated();
    }

    public EventLoopGroup getGroup() {
        return this.group;
    }

    public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
        try {
            return this.timer.newTimeout(task, delay, unit);
        } catch (IllegalStateException var6) {
            if (this.isShuttingDown()) {
                return DUMMY_TIMEOUT;
            } else {
                throw var6;
            }
        }
    }

    public InfinitySemaphoreLatch getShutdownLatch() {
        return this.shutdownLatch;
    }

    public Future<Void> getShutdownPromise() {
        return this.shutdownPromise;
    }

    public ConnectionEventsHub getConnectionEventsHub() {
        return this.connectionEventsHub;
    }

    protected void stopThreads() {
        this.shutdown();
    }

    public PublishSubscribeService getSubscribeService() {
        return this.subscribeService;
    }

    public ElementsSubscribeService getElementsSubscribeService() {
        return this.elementsSubscribeService;
    }

    public ExecutorService getExecutor() {
        return this.executor;
    }

    public RedisURI getLastClusterNode() {
        return null;
    }

    public RedisURI applyNatMap(RedisURI address) {
        return address;
    }
}

3、RedisClient類,創建客戶端連接服務端所需的Bootstrap

private Bootstrap createBootstrap(RedisClientConfig config, Type type) {
        Bootstrap bootstrap = (Bootstrap)((Bootstrap)(new Bootstrap()).resolver(config.getResolverGroup()).channel(config.getSocketChannelClass())).group(config.getGroup());
        bootstrap.handler(new RedisChannelInitializer(bootstrap, config, this, this.channels, type));
        bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, config.getConnectTimeout());
        bootstrap.option(ChannelOption.SO_KEEPALIVE, config.isKeepAlive());
        bootstrap.option(ChannelOption.TCP_NODELAY, config.isTcpNoDelay());
        config.getNettyHook().afterBoostrapInitialization(bootstrap);
        return bootstrap;
    }

4、創建連接   RedisClient類

    public RFuture<RedisConnection> connectAsync() {
        RPromise<RedisConnection> f = new RedissonPromise();
        RFuture<InetSocketAddress> addrFuture = this.resolveAddr();
        addrFuture.onComplete((res, e) -> {
            if (e != null) {
                f.tryFailure(e);
            } else {
                 //netty 異步連接
                ChannelFuture channelFuture = this.bootstrap.connect(res);
                channelFuture.addListener(new ChannelFutureListener() {
                    public void operationComplete(final ChannelFuture future) throws Exception {
                        if (RedisClient.this.bootstrap.config().group().isShuttingDown()) {
                            IllegalStateException cause = new IllegalStateException("RedisClient is shutdown");
                            f.tryFailure(cause);
                        } else {
                            if (future.isSuccess()) {
                                RedisConnection c = RedisConnection.getFrom(future.channel());
                                c.getConnectionPromise().onComplete((res, e) -> {
                                    RedisClient.this.bootstrap.config().group().execute(new Runnable() {
                                        public void run() {
                                            if (e == null) {
                                                if (!fx.trySuccess(c)) {
                                                    c.closeAsync();
                                                }
                                            } else {
                                                fx.tryFailure(e);
                                                c.closeAsync();
                                            }

                                        }
                                    });
                                });
                            } else {
                                RedisClient.this.bootstrap.config().group().execute(new Runnable() {
                                    public void run() {
                                        f.tryFailure(future.cause());
                                    }
                                });
                            }

                        }
                    }
                });
            }
        });
        return f;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章