借助 RESTful 接口, TDengine 的 JDBC 驱动可跨平台,而且不用为升级发愁了

随着 TDengine 2.0.14.0 版本的发布,我们在这个版本中为 JDBC Connector 添加了一种新的实现:JDBC-RESTful,一种基于 RESTful 接口的 JDBC 实现,可以通过 taos-jdbcdriver 2.0.18 来使用这个新特性。

!!!重要的事情先说,使用 JDBC-RESTful 的几个最重要的好处:

  1. TDengine 的应用开发可以跨平台了。之前,由于 TDengine 的 JDBC 驱动依赖本地动态库(Linux 上为 libtaos.so ,windows 上为 taos.dll ),开发者需要先在本地安装客户端。否则,应用程序会报错:no taos in java.library.path。而 TDengine 目前只支持 Linux 和 Windows 操作系统的客户端安装包,并且源码也无法在其他操作系统上编译。这对于使用 macOS 的用户来说,需要先在 macOS 上写好代码,再将代码部署到 Linux 服务器上调试。或者使用像 VS code 等可以支持远程代码开发的 IDE 工具,这些都增加了使用 TDengine 的开发成本。这也是我们为什么要开发 JDBC-RESTful 的原因。使用 JDBC-RESTful 后,不需要安装客户端!不需要使用远程代码开发的 IDE 工具!在 mac 上也可以做开发啦。
  2. 使用 JDBC-RESTful 后,不再需要升级客户端。使用 JDBC-RESTful 后,不需要安装 TDengine 的客户端。对企业应用开发来说,由专门的运维人员来负责 TDengine 的维护和升级,server 端升级后,应用不需要升级 client。
  3. 迁移到 JDBC-RESTful 需要的改动很小。使用 JDBC-RESTful,只需要修改一下 driverClass 和 URL 即可。这对于大部分的 Java 应用来说,只是修改一下配置文件即可。

下面,详细描述一下 JDBC-RESTful 的相关概念和使用方法。

一、JDBC-RESTful 的实现原理

目前,JDBC Connector 的实现包括2种形式: JDBC-JNI 和 JDBC-RESTful。

  • JDBC-JNI :使用JNI调用客户端 libtaos.so(或 taos.dll )的本地方法,通过 socket 与 taosd 通信。
  • JDBC-RESTful :在内部封装了 TDengine 的 RESTful 接口,将 SQL 封装成 HTTP 请求发送给 server 端的 taosd 示例。
3 种 Java 应用使用连接器访问 TDengine 的方式

上图显示了 3 种 Java 应用使用连接器访问 TDengine 的方式:

  • JDBC-JNI:Java 应用在物理节点1(pnode1)上使用 JDBC-JNI 的 API ,直接调用客户端 API(libtaos.so 或 taos.dll)将写入和查询请求发送到位于物理节点 2(pnode2)上的 taosd 实例。
  • RESTful:应用将 SQL 发送给位于物理节点2(pnode2)上的 RESTful 连接器,再调用客户端 API(libtaos.so)。
  • JDBC-RESTful:Java 应用通过 JDBC-RESTful 的 API ,将 SQL 封装成一个 RESTful 请求,发送给物理节点2的 RESTful 连接器。

二、JDBC-RESTful 的使用示例

使用 JDBC-RESTful 接口,与之前的 JDBC-JNI 相比,仅需要:

  1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”;
  2. jdbcUrl 以 “jdbc:TAOS-RS://” 开头;
  3. 使用 6041 作为连接端口。

下面,展示一个完整的使用 JDBC-RESTful 的示例:

(1)在 pom.xml 中引入 taos-jdbcdriver 依赖

<dependency>
  <groupId>com.taosdata.jdbc</groupId>
  <artifactId>taos-jdbcdriver</artifactId>
  <version>2.0.18</version>
</dependency>

(2)示例代码:

public class JdbcRestfulDemo {
    private static final String host = "taos-server";

    public static void main(String[] args) {
        try {
            // load JDBC-restful driver
            Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
            // use port 6041 in url when use JDBC-restful
            String url = "jdbc:TAOS-RS://" + host + ":6041/?user=root&password=taosdata";

            Properties properties = new Properties();
            properties.setProperty("charset", "UTF-8");
            properties.setProperty("locale", "en_US.UTF-8");
            properties.setProperty("timezone", "UTC-8");

            Connection conn = DriverManager.getConnection(url, properties);
            Statement stmt = conn.createStatement();

            stmt.execute("create database if not exists restful_test");
            stmt.execute("use restful_test");
            stmt.execute("create table restful_test.weather(ts timestamp, temperature float) tags(location nchar(64))");
            stmt.executeUpdate("insert into t1 using restful_test.weather tags('北京') values(now, 18.2)");
            ResultSet rs = stmt.executeQuery("select * from restful_test.weather");
            ResultSetMetaData meta = rs.getMetaData();
            while (rs.next()) {
                for (int i = 1; i <= meta.getColumnCount(); i++) {
                    System.out.print(meta.getColumnLabel(i) + ": " + rs.getString(i) + "\t");
                }
                System.out.println();
            }
            rs.close();
            
            stmt.close();
            conn.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

三、JDBC-RESTful 的性能

从上面 JDBC-RESTful 的实现原理看到,JDBC-RESTful 方式相当于对 libtaos.so 的 C 方法进行了两次封装,第一次是 RESTful 对 libtaos.so 中的方法进行了封装,第二次是 taos-jdbcdriver 对 RESTful 接口进行了封装。并且,使用 JDBC-RESTful ,意味着将数据库的访问请求全部发送给了 server ,server 端需要做所有由 client 负责的 SQL 解析、结果集聚合等工作。那么使用 JDBC-RESTful 接口是否会造成性能下降呢?我们内部对 JDBC-RESTful 接口进行了性能测试。

测试环境:CPU:mac pro(6核,Intel Core i7),内存:16 GB ,硬盘:SSD(500GB)

测试记录:

对 JDBC-RESTful 接口测试的记录

测试结论:

  1. 在每条 SQL 中插入的记录数少的情况下,JDBC-RESTful 的写入性能是 JDBC-JNI 的 50% 左右;
  2. 在每条 SQL 中插入的记录数多的情况下,JDBC-RESTful 的写入性能是 JDBC-JNI 性能的 90% 左右;
  3. JDBC-RESTful 与 JDBC-JNI 在查询性能上,没有明显差异。

注意:以上测试的写入性能和查询性能与具体测试环境和配置有关,在不同的测试环境在性能差异上略有不同。

总结

这里,给使用 JDBC-RESTful 的 Java 开发者一些使用建议:

  1. JDBC-RESTful 提供了跨平台开发的特性,可以在开发环境中使用。
  2. JDBC-JNI 相比 JDBC-RESTful 有一定的性能优势,如果在生产环境中希望最大化发挥 TDengine 的性能,可以使用 JDBC-JNI 的方式。
  3. JDBC-RESTful 到 JDBC-JNI 的切换十分简单,一般只需要修改配置文件即可。