Jedis源码学习

jdeis 分析

  • 入口代码

    JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), hnp.getPort(), 2000);
    逐步跟进会初始化一个JedisFactory通过构造方法把后面需要的值提前赋值:
    public JedisPool(final GenericObjectPoolConfig poolConfig, final String host, int port,
      final int connectionTimeout, final int soTimeout, final String password, final int database,
      final String clientName) {
    super(poolConfig, new JedisFactory(host, port, connectionTimeout, soTimeout, password,
        database, clientName));
    }
    
    继续深入点入会初始化连接池:
    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
    GenericObjectPool是apache提供的对象池,需要的参数是PooledObjectFactory,jedis中传入JedisFactory,
    有很多作用,比如连接池中没有对象时,可以调用makeObject方法创建一个连接对象
    GenericObjectPool的构造方法:
    this.idleObjects = new LinkedBlockingDeque(config.getFairness());  初始化一个队列存放连接
    获取池中的对象是通过GenericObjectPool的borrowObject()方法
  • 回到jedis获取连接

    Jedis jedis = pool.getResource(); 获取一个jedis
    getResource:
    return internalPool.borrowObject();   对应上面的GenericObjectPool
    
    public T borrowObject() throws Exception {
        return this.borrowObject(this.getMaxWaitMillis());//最大等待时间
    }
    
    没有连接的时候会去创建:
    p = (PooledObject)this.idleObjects.pollFirst();
                        if (p == null) {
                            p = this.create();//会执行JedisFactory.makeObject方法,创建socket
                            if (p != null) {
                                create = true;
                            }
    }
    
    validate = this.factory.validateObject(p);判断连接是否可用   (通过发送ping命令)
  • JedisFactory.makeObject 方法分析

    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 (password != null) {
        jedis.auth(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);
    
    }
    构造BinaryJedis    (BinaryClient extends Connection)
    public BinaryJedis(final String host, final int port, final int connectionTimeout,
      final int soTimeout, final boolean ssl, final SSLSocketFactory sslSocketFactory,
      final SSLParameters sslParameters, final HostnameVerifier hostnameVerifier) {
    client = new Client(host, port, ssl, sslSocketFactory, sslParameters, hostnameVerifier);
    client.setConnectionTimeout(connectionTimeout);
    client.setSoTimeout(soTimeout);
    }
    
    创建连接:
    public void connect() {
    if (!isConnected()) {
      super.connect();
      if (password != null) {
        auth(password);
        getStatusCodeReply();
      }
      if (db > 0) {
        select(db);
        getStatusCodeReply();
      }
    }
    }
    
    Connection中的connect方法:
    public void connect() {
    if (!isConnected()) {
      try {
        socket = new Socket();
        // ->@wjw_add
        socket.setReuseAddress(true);
        socket.setKeepAlive(true); // Will monitor the TCP connection is
        // valid
        socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
        // ensure timely delivery of data
        socket.setSoLinger(true, 0); // Control calls close () method,
        // the underlying socket is closed
        // immediately
        // <-@wjw_add
    
        socket.connect(new InetSocketAddress(host, port), connectionTimeout);
        socket.setSoTimeout(soTimeout);
    
        if (ssl) {
          if (null == sslSocketFactory) {
            sslSocketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
          }
          socket = sslSocketFactory.createSocket(socket, host, port, true);
          if (null != sslParameters) {
            ((SSLSocket) socket).setSSLParameters(sslParameters);
          }
          if ((null != hostnameVerifier) &&
              (!hostnameVerifier.verify(host, ((SSLSocket) socket).getSession()))) {
            String message = String.format(
                "The connection to '%s' failed ssl/tls hostname verification.", host);
            throw new JedisConnectionException(message);
          }
        }
    
        outputStream = new RedisOutputStream(socket.getOutputStream());
        inputStream = new RedisInputStream(socket.getInputStream());
      } catch (IOException ex) {
        broken = true;
        throw new JedisConnectionException("Failed connecting to host " 
            + host + ":" + port, ex);
      }
    }
    }
    
    具体执行命令:
    jedis.set("foo", "bar");
    public String set(final String key, final String value) {
    checkIsInMultiOrPipeline();
    client.set(key, value);
    return client.getStatusCodeReply();
    }
    connect();
    Protocol.sendCommand(outputStream, cmd, args);
  • 归还连接到池子
    jedis.close();
    pool.destroy(); 
    internalPool.returnObject(resource);  归还资源到连接池

简单来说jedis整个交互过程是一个Socket通信过程。

点赞