南大通用GBase 8a 通过JDBC实现简单负载均衡的测试样例

GBase 8a 的所有调度节点(coordinator)均可以对外提供完整的服务,同时其JDBC/ODBC/C API等驱动,实现了简单的基于轮询(round-robin)的负载均衡机制,本文介绍JDBC的一个样例。

参考

环境

2节点集群,测试10个连接,是否均衡的分布到2个节点上。

[gbase@862b43 ~]$ gcadmin
CLUSTER STATE:  ACTIVE
CLUSTER MODE:   NORMAL

=================================================================
|             GBASE COORDINATOR CLUSTER INFORMATION             |
=================================================================
|   NodeName   |     IpAddress     |gcware |gcluster |DataState |
-----------------------------------------------------------------
| coordinator1 |    10.0.2.106     | OPEN  |  OPEN   |    0     |
-----------------------------------------------------------------
| coordinator2 |    10.0.2.107     | OPEN  |  OPEN   |    0     |
-----------------------------------------------------------------
=============================================================
|              GBASE DATA CLUSTER INFORMATION               |
=============================================================
|NodeName |     IpAddress     |gnode |syncserver |DataState |
-------------------------------------------------------------
|  node1  |    10.0.2.106     | OPEN |   OPEN    |    0     |
-------------------------------------------------------------
|  node2  |    10.0.2.107     | OPEN |   OPEN    |    0     |
-------------------------------------------------------------

代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Test {

        public static void main(String[] args) throws Exception {

                for (int i = 1; i <= 10; i++) {
                        new TestThread(i).start();
                       Thread.sleep(100);
                }
        }
}

class TestThread extends Thread {
        private int id;
        public TestThread(int id) {
                this.id = id;
        }
        public void run() {
                Connection conn = null;
                try {
                        conn = DriverManager.getConnection(
                            "jdbc:gbase://10.0.2.106/testdb?user=gbase&password=gbase20110531&failoverEnable=true&hostList=10.0.2.107&gclusterId=vmax");
                        Statement stat = conn.createStatement();
                        stat.execute("select sleep(10)");

                        conn.close();
                } catch (Exception ex) {
                        System.out.println(id);
                        ex.printStackTrace();
                }
        }
}

运行效果

2个节点,每个上有5个SQL在运行。


[gbase@localhost ~]$ gccli -h10.0.2.106 -e"show processlist"
+----+-----------------+------------------+--------+---------+------+---------------------------+------------------+
| Id | User            | Host             | db     | Command | Time | State                     | Info             |
+----+-----------------+------------------+--------+---------+------+---------------------------+------------------+
|  1 | event_scheduler | localhost        | NULL   | Daemon  |  564 | Waiting for cluster mutex | NULL             |
| 75 | gbase           | 10.0.2.106:42850 | testdb | Query   |    3 | checking permissions      | select sleep(10) |
| 76 | gbase           | 10.0.2.106:42854 | testdb | Query   |    3 | checking permissions      | select sleep(10) |
| 77 | gbase           | 10.0.2.106:42856 | testdb | Query   |    3 | checking permissions      | select sleep(10) |
| 78 | gbase           | 10.0.2.106:42860 | testdb | Query   |    3 | checking permissions      | select sleep(10) |
| 79 | gbase           | 10.0.2.106:42864 | testdb | Query   |    3 | checking permissions      | select sleep(10) |
| 80 | root            | 10.0.2.107:54660 | NULL   | Query   |    0 | NULL                      | show processlist |
+----+-----------------+------------------+--------+---------+------+---------------------------+------------------+
[gbase@localhost ~]$ gccli -h10.0.2.107 -e"show processlist"
+----+-----------------+------------------+--------+---------+------+-----------------------------+------------------+
| Id | User            | Host             | db     | Command | Time | State                       | Info             |
+----+-----------------+------------------+--------+---------+------+-----------------------------+------------------+
|  1 | event_scheduler | localhost        | NULL   | Daemon  |  560 | Waiting for next activation | NULL             |
| 27 | gbase           | 10.0.2.106:50112 | testdb | Query   |    5 | checking permissions        | select sleep(10) |
| 28 | gbase           | 10.0.2.106:50114 | testdb | Query   |    5 | checking permissions        | select sleep(10) |
| 29 | gbase           | 10.0.2.106:50118 | testdb | Query   |    5 | checking permissions        | select sleep(10) |
| 30 | gbase           | 10.0.2.106:50124 | testdb | Query   |    5 | checking permissions        | select sleep(10) |
| 31 | gbase           | 10.0.2.106:50128 | testdb | Query   |    5 | checking permissions        | select sleep(10) |
| 32 | root            | 10.0.2.107:58220 | NULL   | Query   |    0 | NULL                        | show processlist |
+----+-----------------+------------------+--------+---------+------+-----------------------------+------------------+
[gbase@localhost ~]$

总结

该负载均衡功能实现很简单,没有判断节点的真实负载、运行中的SQL数量等,只是简单的循环。如果想实现更好的,建议采用F5设备,或者用lvs等第三方软件实现。

另外,如果使用了连接池,那么只能保证连接池里每个新建的连接是循环产生的,但不能保证应用从连接池里获得连接时,也是循环的。如果服务器有节点故障,那么连接池里将不包含该节点的连接,即使节点恢复正常,除非连接池刷新,否则依然保持现状。