3.Mycat原理解析-后端连接管理

一、数据源与连接池

  前面我们说过,Mycat除了作为服务端外,还作为客户端来连接数据库,所以需要管理与数据库的连接。在管理后端连接中,主要涉及到下面两个类。

  • PhysicalDatasource
  • BackendConnection

      从下面的类图可以看出,同普通的数据源一样,PhysicalDatasource负责建立连接,并且内部维护了一个连接池——conMap。
      Mycat目前提供了三种数据源的实现:MySQLDatasource、PostgreSQLDataSource、JDBCDatasource。其中,MySQLDatasource和PostgreSQLDataSource是通过NIO与MySQL通信,JDBCDatasource是通过传统的JDBC Driver(也就是BIO)与MySQL通信。也就是说,如果你的数据库用的是MySQL和PostgreSQL,那么后端通信用的是NIO,否则用的就是BIO。

这里写图片描述

二、获取后端连接

  通过PhysicalDatasource的getConnection方法来获取连接时,返回值是void,这是因为Mycat后端的所有操作都是通过回调来完成的,当获取到连接后,会调用ResponseHandler的connectionAcquired()方法。
  如果当前连接池中没有连接,就会异步创建新的连接,对于MySQL和PostgreSQL,通过工厂创建连接对象,注入一个SocketChannel实例。真正的创建过程交给NIOConnector处理;对于其他数据库,直接通过DriverManager来建立新的连接。

public void getConnection(String schema, boolean autocommit,
    final ResponseHandler handler, final Object attachment)
        throws IOException {
    // 从当前连接map中拿取已建立好的后端连接
    BackendConnection con = this.conMap.tryTakeCon(schema, autocommit);
    if (con != null) {
        //如果不为空,则绑定对应前端请求的handler
        takeCon(con, handler, attachment, schema);
        return;
    } else {
        int curTotalConnection = this.totalConnection.get();
        synchronized (this) {
            while (curTotalConnection + 1 <= size) {
                if (this.totalConnection.compareAndSet(curTotalConnection, curTotalConnection + 1)) {
                    //没有空闲连接,创建新的连接
                    createNewConnection(handler, attachment, schema);
                    return;
                }
                //CAS更新失败,则重新判断当前连接是否超过最大连接数
                curTotalConnection = this.totalConnection.get(); 
            }
        }
        // 如果后端连接不足,立即失败,故直接抛出连接数超过最大连接异常
        throw new IOException("the max activeConnnections size can not be max than maxconnections:" + curTotalConnection);
    }
}

private BackendConnection takeCon(BackendConnection conn,
        final ResponseHandler handler, final Object attachment,
        String schema) {
    conn.setBorrowed(true);
    if (!conn.getSchema().equals(schema)) {
        // need do schema syn in before sql send
        conn.setSchema(schema);
    }
    ConQueue queue = conMap.getSchemaConQueue(schema);
    queue.incExecuteCount();
    conn.setAttachment(attachment);
    // 每次取连接的时候,更新下lasttime,防止在前端连接检查的时候,关闭连接,导致sql执行失败
    conn.setLastTime(System.currentTimeMillis()); 
    incrementActiveCountSafe(conn);
    handler.connectionAcquired(conn);
    return conn;
}

private void createNewConnection(final ResponseHandler handler,
        final Object attachment, final String schema) throws IOException {      
    // aysn create connection
    MycatServer.getInstance().getBusinessExecutor().execute(new Runnable() {
        public void run() {
            try {
                createNewConnection(new DelegateResponseHandler(handler) {
                    @Override
                    public void connectionError(Throwable e, BackendConnection conn) {
                        // 如果创建连接失败,将当前连接数减1
                        decrementTotalConnectionsSafe(); 
                        handler.connectionError(e, conn);
                    }

                    @Override
                    public void connectionAcquired(BackendConnection conn) {
                        takeCon(conn, handler, attachment, schema);
                    }
                }, schema);
            } catch (IOException e) {
                handler.connectionError(e, null);
            }
        }
    });
}

三、空闲连接心跳检测

首先需要明确下面几个概念:

  • 总连接数=活跃连接数+空闲连接数
  • 活跃连接数
  • 空闲连接数
  • 最小连接数
  • 最小空闲连接数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值