jedis源码阅读

一、jedis连接池

jedis是连接redis的java客户端,连接池负责管理jedis与redis服务器的连接。

二、连接池创建

JedisPool提供了很多构造方法,可根据需要调用,如public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,  int timeout, final String password)

最终都会调用父类pool的方法:

public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
    initPool(poolConfig, factory);

  }

public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {
    if (this.internalPool != null) {
      try {
        closeInternalPool();
      } catch (Exception e) {
      }
    }
    this.internalPool = new GenericObjectPool<T>(factory, poolConfig);

  }

最终调用通用对象连接池GenericObjectPool类创建连接池。

 public GenericObjectPool(PooledObjectFactory<T> factory,
            GenericObjectPoolConfig config) {
        super(config, ONAME_BASE, config.getJmxNamePrefix());
        if (factory == null) {
            jmxUnregister(); // tidy up
            throw new IllegalArgumentException("factory may not be null");
        }
        this.factory = factory;
        //创建连接对象队列
        idleObjects = new LinkedBlockingDeque<PooledObject<T>>(config.getFairness());
        //设置配置参数

        setConfig(config);

        startEvictor(getTimeBetweenEvictionRunsMillis());  // 启动定时任务回收空闲连接

    }

private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =

        new ConcurrentHashMap<IdentityWrapper<T>, PooledObject<T>>(); // 除了被销毁的所有对象

private final LinkedBlockingDeque<PooledObject<T>> idleObjects;// 空闲对象

三、获取连接

获取连接入口方法在JedisPool的

public Jedis getResource() {

    Jedis jedis = super.getResource();
    jedis.setDataSource(this);
    return jedis;

  }

调用父类pool的public T getResource() {
    try {
      return internalPool.borrowObject();
    } catch (NoSuchElementException nse) {
      throw new JedisException("Could not get a resource from the pool", nse);
    } catch (Exception e) {
      throw new JedisConnectionException("Could not get a resource from the pool", e);
    }

  }

从连接池里获取连接,获取连接核心代码GenericObjectPool的borrowObject方法:

public T borrowObject(long borrowMaxWaitMillis) throws Exception {
        assertOpen();
        AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
                (getNumIdle() < 2) &&
                (getNumActive() > getMaxTotal() - 3) ) {
            removeAbandoned(ac);
        }
        PooledObject<T> p = null;
        // 连接池没有可用连接(无空闲或为空)是否阻塞等待
        boolean blockWhenExhausted = getBlockWhenExhausted();
        boolean create; //本次连接是否新创建标志
        long waitTime = System.currentTimeMillis();

        while (p == null) {
            create = false;
            if (blockWhenExhausted) {
                p = idleObjects.pollFirst();//返回空闲连接队列的第一个对象
                if (p == null) {
                    p = create();// 创建新连接
                    if (p != null) {
                        create = true;
                    }
                }
                if (p == null) {
                    if (borrowMaxWaitMillis < 0) {
                        p = idleObjects.takeFirst(); //阻塞获取空闲队列的第一个连接对象
                    } else {
                        p = idleObjects.pollFirst(borrowMaxWaitMillis,
                                TimeUnit.MILLISECONDS);//根据超时时间返回空闲连接队列的第一个对象
                    }
                }
                if (p == null) {
                    throw new NoSuchElementException(
                            "Timeout waiting for idle object");
                }
                if (!p.allocate()) {
                    p = null;
                }
            } else {
                p = idleObjects.pollFirst();
                if (p == null) {
                    p = create();
                    if (p != null) {
                        create = true;
                    }
                }
                if (p == null) {
                    throw new NoSuchElementException("Pool exhausted");
                }
                if (!p.allocate()) {
                    p = null;
                }

            }

            if (p != null) {
                try {
                    factory.activateObject(p);  //激活资源对象
                } catch (Exception e) {
                    try {
                        destroy(p);
                    } catch (Exception e1) {
                        // Ignore - activation failure is more important
                    }
                    p = null;
                    if (create) {
                        NoSuchElementException nsee = new NoSuchElementException(
                                "Unable to activate object");
                        nsee.initCause(e);
                        throw nsee;
                    }
                }
                if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {
                    boolean validate = false;
                    Throwable validationThrowable = null;
                    try {
                        validate = factory.validateObject(p); //检查对象是否有效
                    } catch (Throwable t) {
                        PoolUtils.checkRethrow(t);
                        validationThrowable = t;
                    }
                    if (!validate) {
                        try {
                            destroy(p); //无效时销毁对象
                            destroyedByBorrowValidationCount.incrementAndGet();
                        } catch (Exception e) {
                            // Ignore - validation failure is more important
                        }
                        p = null;
                        if (create) {
                            NoSuchElementException nsee = new NoSuchElementException(
                                    "Unable to validate object");
                            nsee.initCause(validationThrowable);
                            throw nsee;
                        }
                    }
                }
            }
        }

        updateStatsBorrow(p, System.currentTimeMillis() - waitTime);

        return p.getObject();
    }

 当没有可用连接调用create方法创建资源对象代码:

private PooledObject<T> create() throws Exception {
        int localMaxTotal = getMaxTotal();
        long newCreateCount = createCount.incrementAndGet();
        if (localMaxTotal > -1 && newCreateCount > localMaxTotal ||
                newCreateCount > Integer.MAX_VALUE) {
            createCount.decrementAndGet();
            return null;
        }
        final PooledObject<T> p;
        try {
            p = factory.makeObject(); //调用工厂类创建对象
        } catch (Exception e) {
            createCount.decrementAndGet();
            throw e;
        }
        AbandonedConfig ac = this.abandonedConfig;
        if (ac != null && ac.getLogAbandoned()) {
            p.setLogAbandoned(true);
        }
        createdCount.incrementAndGet();
        allObjects.put(new IdentityWrapper<T>(p.getObject()), p);
        return p;
    }

工厂类JedisFactory创建资源连接对象代码:

public PooledObject<Jedis> makeObject() throws Exception {
    final HostAndPort hostAndPort = this.hostAndPort.get();
    final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout,
        soTimeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    try {
      jedis.connect();
      if (null != this.password) {
        jedis.auth(this.password);
      }
      if (database != 0) {
        jedis.select(database);
      }
      if (clientName != null) {
        jedis.clientSetname(clientName);
      }
    } catch (JedisException je) {
      jedis.close();
      throw je;
    }
    return new DefaultPooledObject<Jedis>(jedis);

  }

四、关闭连接

获取连接后需要调用关闭连接jedis.close();方法,释放连接,该方法只是释放资源到连接池,并不会真正关闭与redis服务器的连接。

Jedis类的close代码:

public void close() {
    if (dataSource != null) { //如果有连接池,就调用连接池的方法
      if (client.isBroken()) {
        this.dataSource.returnBrokenResource(this);
      } else {
        this.dataSource.returnResource(this);
      }
    } else { // 如果没有连接池,则直接断开与服务器的连接
      client.close();
    }

  }

JredisPool类returnResource释放连接的代码:

public void returnResource(final Jedis resource) {
    if (resource != null) {
      try {
        resource.resetState();
        returnResourceObject(resource);
      } catch (Exception e) {
        returnBrokenResource(resource);
        throw new JedisException("Could not return the resource to the pool", e);
      }
    }

  }

public void returnResourceObject(final T resource) {
    if (resource == null) {
      return;
    }
    try {
      internalPool.returnObject(resource);
    } catch (Exception e) {
      throw new JedisException("Could not return the resource to the pool", e);
    }
  }

释放资源的核心方法returnObject代码:

public void returnObject(T obj) {
        PooledObject<T> p = allObjects.get(new IdentityWrapper<T>(obj)); // 获取要释放的连接
        if (p == null) {
            if (!isAbandonedConfig()) {
                throw new IllegalStateException(
                        "Returned object not currently part of this pool");
            } else {
                return; // Object was abandoned and removed
            }
        }
        synchronized(p) {
            final PooledObjectState state = p.getState();
            if (state != PooledObjectState.ALLOCATED) {
                throw new IllegalStateException(
                        "Object has already been returned to this pool or is invalid");
            } else {
                p.markReturning(); // Keep from being marked abandoned
            }
        }
        long activeTime = p.getActiveTimeMillis();
        if (getTestOnReturn()) {
            if (!factory.validateObject(p)) {
                try {
                    destroy(p); //销毁对象
                } catch (Exception e) {
                    swallowException(e);
                }
                try {
                    ensureIdle(1, false);
                } catch (Exception e) {
                    swallowException(e);
                }
                updateStatsReturn(activeTime);
                return;
            }
        }
        try {
            factory.passivateObject(p); //钝化对象
        } catch (Exception e1) {
            swallowException(e1);
            try {
                destroy(p);
            } catch (Exception e) {
                swallowException(e);
            }
            try {
                ensureIdle(1, false);
            } catch (Exception e) {
                swallowException(e);
            }
            updateStatsReturn(activeTime);
            return;
        }
        if (!p.deallocate()) {
            throw new IllegalStateException(
                    "Object has already been returned to this pool or is invalid");
        }
        int maxIdleSave = getMaxIdle();
        if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { //如果空闲队列已达到配置值,则直接销毁连接
            try {
                destroy(p);
            } catch (Exception e) {
                swallowException(e);
            }

        } else { 

         if (getLifo()) {

                idleObjects.addFirst(p);
            } else {
                idleObjects.addLast(p);
            } //将连接放入空闲对象队列,默认先进先出
            if (isClosed()) {
                // Pool closed while object was being added to idle objects.
                // Make sure the returned object is destroyed rather than left
                // in the idle object pool (which would effectively be a leak)
                clear();
            }
        }
        updateStatsReturn(activeTime);
    }

猜你喜欢

转载自blog.csdn.net/long2010110/article/details/80707101
今日推荐