在搭建工业物联网的数据平台,用来完成设备连接以及数据存储等,
以支持上层的应用及数据分析等。目前使用的是mq→flink→influxdb的基本套路。
虽然说InfluxDB的性能和功能都非常的棒,特别是连续查询对性能的支撑,
不过由于influxdb使用的是社区版,存在单点故障的问题,总之不是长久直接。
于是打算尝试验证一下陶老师的TDEngine。祝自己一切顺利。
服务器节点数:3个(VMware虚拟机)
操作系统:Linux Centos8 64位
TDengine版本:2.0.4
JDK:1.8.0_77
https://www.taosdata.com/cn/getting-started/
TDengine-server-2.0.4.0-Linux-x64.rpm TDengine-client-2.0.4.0-Linux-x64.tar.gz TDengine-alert-2.0.4.0-Linux-x64.tar.gz
参考官网:https://www.taosdata.com/cn/documentation/cluster/
PS:中文文档是真的很爽,比看英文省心多了。
上传到服务器,并复制到各个节点,在各个节点执行rpm安装命令
命令:rpm -ivh TDengine-server-2.0.4.0-Linux-x64.rpm
配置文件路径:/etc/taos/taos.cfg
配置文件说明:TDengine的运营与维护
按照官网的提示,修改了几个配置:firstEp、secondEp、fqdn、serverPort、logDir、dataDir、replica。
根据官网的说明,我罗列了配置的中文,供参考。没有写的是在这个版本的官网上没有找到的了。
######################################################## # # # TDengine Configuration # # Any questions, please email support@taosdata.com # # # ######################################################## # first fully qualified domain name (FQDN) for TDengine system # taosd启动时,主动连接的集群中第一个dnode的end point, 默认值为localhost:6030。 firstEp vm1:6030 # second fully qualified domain name (FQDN) for TDengine system, for cluster only # taosd启动时,如果first连接不上,尝试连接集群中第二个dnode的end point, 默认值为空。 secondEp vm2:6030 # local fully qualified domain name (FQDN) # 数据节点的FQDN,缺省为操作系统配置的第一个hostname。如果习惯IP地址访问,可设置为该节点的IP地址。 fqdn vm1 # first port number for the connection (12 continuous UDP/TCP port number are used) # taosd启动后,对外服务的端口号,默认值为6030。 serverPort 6030 # log file‘s directory # 日志文件目录,客户端和服务器的运行日志文件将写入该目录。默认值:/var/log/taos。 logDir /home/radmin/data/tdengine/log # data file‘s directory # 数据文件目录,所有的数据文件都将写入该目录。默认值:/var/lib/taos。 dataDir /home/radmin/data/tdengine/data # the arbitrator‘s fully qualified domain name (FQDN) for TDengine system, for cluster only # 系统中裁决器的end point, 缺省值为空。 # arbitrator arbitrator_hostname:6042 # number of threads per CPU core # numOfThreadsPerCore 1.0 # number of management nodes in the system # 系统中管理节点个数。默认值:3。 # numOfMnodes 3 # enable/disable backuping vnode directory when removing dnode # vnodeBak 1 # enable/disable load balancing # 是否启动负载均衡。0:否,1:是。默认值:1。 # balance 1 # role for dnode. 0 - any, 1 - mnode, 2 - dnode # dnode的可选角色。0-any; 既可作为mnode,也可分配vnode;1-mgmt;只能作为mnode,不能分配vnode;2-dnode;不能作为mnode,只能分配vnode # role 0 # max timer control blocks # maxTmrCtrl 512 # time interval of system monitor, seconds # monitorInterval 30 # number of seconds allowed for a dnode to be offline, for cluster only # dnode离线阈值,超过该时间将导致该dnode从集群中删除。单位为秒,默认值:86400*10(即10天)。 # offlineThreshold 8640000 # RPC re-try timer, millisecond # rpcTimer 300 # RPC maximum time for ack, seconds. # rpcMaxTime 600 # time interval of dnode status reporting to mnode, seconds, for cluster only # statusInterval 1 # time interval of heart beat from shell to dnode, seconds # shellActivityTimer 3 # time of keeping table meta data in cache, seconds # tableMetaKeepTimer 7200 # minimum sliding window time, milli-second # minSlidingTime 10 # minimum time window, milli-second # minIntervalTime 10 # maximum delay before launching a stream compution, milli-second # maxStreamCompDelay 20000 # maximum delay before launching a stream computation for the first time, milli-second # maxFirstStreamCompDelay 10000 # retry delay when a stream computation fails, milli-second # retryStreamCompDelay 10 # the delayed time for launching a stream computation, from 0.1(default, 10% of whole computing time window) to 0.9 # streamCompDelayRatio 0.1 # max number of vgroups per db, 0 means configured automatically # 每个数据库中能够使用的最大vnode个数。 # maxVgroupsPerDb 0 # max number of tables per vnode # 每个vnode中能够创建的最大表个数。默认值:1000000。 # maxTablesPerVnode 1000000 # step size of increasing table number in a vnode # tableIncStepPerVnode 1000 # cache block size (Mbyte) # cache 16 # number of cache blocks per vnode # blocks 6 # number of days per DB file # 一个数据文件存储数据的时间跨度,单位为天,默认值:10。 # days 10 # number of days to keep DB file # 数据库中数据保留的天数,单位为天,默认值:3650。 # keep 3650 # minimum rows of records in file block # 文件块中记录的最小条数,单位为条,默认值:100。 # minRows 100 # maximum rows of records in file block # 文件块中记录的最大条数,单位为条,默认值:4096。 # maxRows 4096 # enable/disable compression # 文件压缩标志位,0:关闭,1:一阶段压缩,2:两阶段压缩。默认值:2。 # comp 2 # write ahead log (WAL) level, 0: no wal; 1: write wal, but no fysnc; 2: write wal, and call fsync # WAL级别。1:写wal, 但不执行fsync; 2:写wal, 而且执行fsync。默认值:1。 # walLevel 1 # if walLevel is set to 2, the cycle of fsync being executed, if set to 0, fsync is called right away # 当wal设置为2时,执行fsync的周期。设置为0,表示每次写入,立即执行fsync。单位为毫秒,默认值:3000。 # fsync 3000 # number of replications, for cluster only # 副本个数,取值范围:1-3。单位为个,默认值:1 replica 2 # mqtt hostname # mqttHostName test.mosquitto.org # mqtt port # mqttPort 1883 # mqtt topic # mqttTopic /test # the compressed rpc message, option: # -1 (no compression) # 0 (all message compressed), # > 0 (rpc message body which larger than this value will be compressed) # compressMsgSize -1 # max length of an SQL # 单条SQL语句允许最长限制。默认值:65380字节。 # maxSQLLength 65480 # the maximum number of records allowed for super table time sorting # maxNumOfOrderedRes 100000 # system time zone # 默认值:从系统中动态获取当前的时区设置 # timezone Asia/Shanghai (CST, +0800) # system locale # 默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置 # locale en_US.UTF-8 # default system charset # 默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置 # charset UTF-8 # max number of connections allowed in dnode # maxShellConns 5000 # max numerber of connections allowed in client # maxConnections 5000 # stop writing logs when the disk size of the log folder is less than this value # minimalLogDirGB 0.1 # stop writing temporary files when the disk size of the log folder is less than this value # minimalTmpDirGB 0.1 # stop writing data when the disk size of the log folder is less than this value # minimalDataDirGB 0.1 # enbale/disable http service # http 1 # enable/disable muqq service # mqtt 0 # enable/disable system monitor # monitor 1 # enable/disable recording the SQL statements via restful interface # httpEnableRecordSql 0 # number of threads used to process http requests # httpMaxThreads 2 # maximum number of rows returned by the restful interface # restfulRowLimit 10240 # The following parameter is used to limit the maximum number of lines in log files. # max number of rows per log filters # 单个日志文件允许的最大行数。默认值:10,000,000行。 # numOfLogLines 10000000 # time of keeping log files, days # 日志文件的最长保存时间。大于0时,日志文件会被重命名为taosdlog.xxx,其中xxx为日志文件最后修改的时间戳,单位为秒。默认值:0天。 # logKeepDays 0 # enable/disable async log # asyncLog 1 # The following parameters are used for debug purpose only. # debugFlag 8 bits mask: FILE-SCREEN-UNUSED-HeartBeat-DUMP-TRACE_WARN-ERROR # 131: output warning and error, 135: output debug, warning and error, 143 : output trace, debug, warning and error to log. # 199: output debug, warning and error to both screen and file # 207: output trace, debug, warning and error to both screen and file # debug flag for all log type, take effect when non-zero value # debugFlag 0 # debug flag for meta management messages # mDebugFlag 135 # debug flag for dnode messages # dDebugFlag 135 # debug flag for sync module # sDebugFlag 135 # debug flag for WAL # wDebugFlag 135 # debug flag for SDB # sdbDebugFlag 135 # debug flag for RPC # rpcDebugFlag 131 # debug flag for TAOS TIMER # tmrDebugFlag 131 # debug flag for TDengine client # cDebugFlag 131 # debug flag for JNI # jniDebugflag 131 # debug flag for ODBC # odbcDebugflag 131 # debug flag for storage # uDebugflag 131 # debug flag for http server # httpDebugFlag 131 # debug flag for mqtt # mqttDebugFlag 131 # debug flag for monitor # monitorDebugFlag 131 # debug flag for query # qDebugflag 131 # debug flag for vnode # vDebugflag 131 # debug flag for http server # tsdbDebugFlag 131 # enable/disable recording the SQL in taos client # tscEnableRecordSql 0 # generate core file when service crash # enableCoreFile 1 # maximum display width of binary and nchar fields in the shell. The parts exceeding this limit will be hidden # maxBinaryDisplayWidth 30
PS:到此的感受:
总体感觉TDengine的安装非常容易,配置文件也简单易懂,到此体验良好。
命令:systemctl start taosd
命令:taos
命令:show dnodes;
先将后两个节点的服务启动起来。
在每个节点执行:systemctl start taosd
确认服务状态:systemctl status taosd
如下图,第2个节点的服务正常:
第3个节点的服务正常:
【小插曲】
在启动第2个节点的时候报错,
[root@vm2 ~]# systemctl status taosd ● taosd.service - TDengine server service Loaded: loaded (/etc/systemd/system/taosd.service; enabled; vendor preset: disabled) Active: failed (Result: start-limit) since Tue 2020-09-29 20:38:20 UTC; 2s ago Process: 5095 ExecStart=/usr/bin/taosd (code=exited, status=1/FAILURE) Main PID: 5095 (code=exited, status=1/FAILURE) Sep 29 20:38:20 vm2 systemd[1]: taosd.service: main process exited, code=exited, status=1/FAILURE Sep 29 20:38:20 vm2 systemd[1]: Unit taosd.service entered failed state. Sep 29 20:38:20 vm2 systemd[1]: taosd.service failed. Sep 29 20:38:20 vm2 systemd[1]: taosd.service holdoff time over, scheduling restart. Sep 29 20:38:20 vm2 systemd[1]: Stopped TDengine server service. Sep 29 20:38:20 vm2 systemd[1]: start request repeated too quickly for taosd.service Sep 29 20:38:20 vm2 systemd[1]: Failed to start TDengine server service. Sep 29 20:38:20 vm2 systemd[1]: Unit taosd.service entered failed state. Sep 29 20:38:20 vm2 systemd[1]: taosd.service failed.
【原因】
没有创建log和data的文件路径,在第2个和第3个节点上分别创建两个路径
mkdir -p /home/radmin/data/tdengine/log
mkdir -p /home/radmin/data/tdengine/data
在第一个数据节点,使用CLI程序taos, 登录进TDengine系统, 执行命令:
CREATE DNODE "vm2:6030"; CREATE DNODE "vm3:6030";
查看新的节点是否加入进来。
【小插曲】
执行show dnodes;之后,发现vm2这个节点处于offline状态。按照官网提示的方法:
查看日志中提示如下错误:
09/29 20:59:55.055274 0x7fcb0aae7700 DND ERROR status rsp is received, error:Cluster cfg inconsistent 09/29 20:59:56.060418 0x7fcb0aae7700 DND ERROR status rsp is received, error:Cluster cfg inconsistent 09/29 20:59:57.065157 0x7fcb0aae7700 DND ERROR status rsp is received, error:Cluster cfg inconsistent
【原因】
经过群里的咨询,有朋友建议排查一下时区是否一致,经排查第2个节点的时区确实与另外两个不一致。
修改了一下时区之后,从新启动第2个节点,发现状态恢复正常。修改时区命令:
mv /etc/localtime /etc/localtime.bak ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/locaktime
【小插曲2】
解决了上面的小插曲,非常的开心,合上笔记本电脑回家。
回家之后,重新连接上服务器,查看状态,结果发现第2个节点的状态又变成offline了,真是开心不过3分钟啊。
【原因】
发现时间貌似不同步。看来是时候加上NTP时间同步了。按照以下步骤尝试了一下
1)停掉taos服务
2)配置ntp同步(参考我的另一篇博客:Linux配置ntp时间服务器)
3)重启taos服务
重启之后,第2个节点的状态恢复为ready,开森。
为了以防万一,将系统放置了一整夜,第2天早上起来查看集群状态,依然是正常的,这下才算放心。
【感谢道友】
添加数据节点:CREATE DNODE "fqdn:port"; 删除数据节点:DROP DNODE "fqdn:port"; 查看数据节点:SHOW DNODES;
PS:到此的感受
TDengine的集群部署也非常的简单,比传统的HBase,MongoDB之类的简单的多,感受不错。
唯一比较大的遗憾是,目前的社区版不支持多级存储,我们实际项目中磁盘是插满的,
如果要利用磁盘空间,就必须要加上lvm,但是lvm会影响读写速度,对已经存在的hdfs也有一些影响。
官网提供了完整的文档,官网地址:https://www.taosdata.com/cn/documentation20/taos-sql/
我个人习惯了逐个尝试验证一遍,以加深印象,好记性不如烂笔头。
另外,可以通过官方提供的样例数据创建一些表供验证。
命令:taosdemo(注意,需要预留大约2.1GB的存储空间)
#创建库: create database mydb keep 365 days 10 blocks 4; #创建库(如果不存在): create database if not exists mydb keep 365 days 10 blocks 4; #使用库: use mydb; #删除库: drop database mydb; #删除库(如果存在): drop database if exists mydb; #显示所有数据库: show databases; #修改数据库文件压缩标志位: alter database mydb comp 2; #修改数据库副本数: alter database mydb replica 2; #修改数据文件保存的天数: alter database mydb keep 365; #修改数据写入成功所需要的确认数: alter database mydb quorum 2; #修改每个VNODE (TSDB) 中有多少cache大小的内存块: alter database mydb blocks 100;
#创建表(搞了个包含所有数据类型的表): create table if not exists mytable(time timestamp, intfield int, bigintfield bigint, floatfield float, doublefield double, binaryfield binary(20), smallintfield smallint, tinyintfield tinyint, boolfield bool, ncharfiel d nchar(50)); #删除数据表 drop table if exists mytable; #显示当前数据库下的所有数据表信息 show tables; #显示当前数据库下的所有数据表信息 #可在like中使用通配符进行名称的匹配。通配符匹配:1)’%’ (百分号)匹配0到任意个字符;2)’_’下划线匹配一个字符。 show tables like "%my%"; #获取表的结构信息 describe mytable; #表增加列 alter table mytable add column addfield int; #表删除列 alter table mytable drop column addfield;
#创建超级表 #创建STable, 与创建表的SQL语法相似,但需指定TAGS字段的名称和类型。说明: #1) TAGS 列的数据类型不能是timestamp类型; #2) TAGS 列名不能与其他列名相同; #3) TAGS 列名不能为预留关键字; #4) TAGS 最多允许128个,可以0个,总长度不超过16k个字符 create table if not exists mysupertable (time timestamp, intfield int, bigintfield bigint, floatfield float, doublefield double, binaryfield binary(20), smallintfield smallint, tinyintfield tinyint, boolfield bool, nch arfield nchar(50)) TAGS (product nchar(50), device nchar(100)); #删除超级表 drop table if exists mysupertable; #显示当前数据库下的所有超级表信息 show stables like "%super%"; #获取超级表的结构信息 describe mysupertable; #超级表增加列 alter table mysupertable add column addfield int; #超级表删除列 alter table mysupertable drop column addfield; #添加标签 alter table mysupertable add tag devicetype nchar(60); #删除标签 alter table mysupertable drop tag devicetype; #修改标签名 alter table mysupertable change tag product productKey; #修改子表标签值 #说明:除了更新标签的值的操作是针对子表进行,其他所有的标签操作(添加标签、删除标签等)均只能作用于STable,不能对单个子表操作。对STable添加标签以后,依托于该STable建立的所有表将自动增加了一个标签,所有新增标签的默认值都是NULL。 alter table mysupertable set tag productkey="abc";
#插入一条数据 insert into mytable values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s"); #插入一条记录,数据对应到指定的列 insert into mytable(time, intfield, bigintfield, floatfield, doublefield, binaryfield, smallintfield, tinyintfield, boolfield, ncharfield) values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s"); #插入多条记录 insert into mytable values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s") (now, 2, 3, 4, 5, 6, 7, 8, 0, "t"); #按指定的列插入多条记录 insert into mytable(time, intfield, bigintfield, floatfield, doublefield, binaryfield, smallintfield, tinyintfield, boolfield, ncharfield) values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s") (now, 2, 3, 4, 5, 6, 7, 8, 0, "t"); #向多个表插入多条记录(老衲我没有验证) INSERT INTO tb1_name VALUES (field1_value1, ...)(field1_value2, ...) tb2_name VALUES (field1_value1, ...)(field1_value2, ...); #同时向多个表按列插入多条记录(老衲我没有验证) INSERT INTO tb1_name (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) tb2_name (tb2_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...);
【小插入】
插入多条记录的时候,语句中写的是两条数据,实际上只插入了一条
插入语句:
insert into mytable(time, intfield, bigintfield, floatfield, doublefield, binaryfield, smallintfield, tinyintfield, boolfield, ncharfield) values(now, 1, 2, 3, 4, 0, 6, 7, 1, "s") (now, 2, 3, 4, 5, 6, 7, 8, 0, "t");
【原因】
需要使用不同的时间戳,如果两条语句都使用now,时间戳一样,最终只能插入一条。
【感谢道友】
查询语法:
SELECT select_expr [, select_expr ...] FROM {tb_name_list} [WHERE where_condition] [INTERVAL (interval_val [, interval_offset])] [FILL fill_val] [SLIDING fill_val] [GROUP BY col_list] [ORDER BY col_list { DESC | ASC }] [SLIMIT limit_val [, SOFFSET offset_val]] [LIMIT limit_val [, OFFSET offset_val]] [>> export_file]
#创建用户,并指定用户名和密码,密码需要用单引号引起来,单引号为英文半角 create user admin pass ‘admin123‘; #删除用户,限root用户使用 drop user admin; #修改用户密码, 为避免被转换为小写,密码需要用单引号引用,单引号为英文半角 alter user admin pass ‘admin1234‘; #修改用户权限为:super/write/read。 为避免被转换为小写,密码需要用单引号引用,单引号为英文半角 #语法:ALTER USER <user_name> PRIVILEDGE <‘super‘|‘write‘|‘read‘>; alter user admin privilege ‘read‘;
【小插曲】
修改用户权限报错,已经提了issue,尚没有解决。
官网地址:https://www.taosdata.com/cn/documentation/connector-java/
<dependency> <groupId>com.taosdata.jdbc</groupId> <artifactId>taos-jdbcdriver</artifactId> <version>2.0.4</version> </dependency>
【TdUtils.java】
单例工具类,实现创建连接等通用方法。
package com.rexel.tdengine.utils; import com.taosdata.jdbc.TSDBDriver; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; /** * @ClassName TdUtils * @Description TDengine共通类 * @Author: chunhui.qu * @Date: 2020/9/30 */ public class TdUtils { private Connection connection = null; /** * 构造函数 */ private TdUtils() { // do nothing } /** * 单例模式 */ private static class SingletonInstance { private static final TdUtils INSTANCE = new TdUtils(); } /** * 获取对象句柄 */ public static TdUtils getInstance() { return SingletonInstance.INSTANCE; } public Connection getConnection() { if (connection != null) { return connection; } try { Class.forName("com.taosdata.jdbc.TSDBDriver"); Properties connProps = new Properties(); connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "/etc/taos"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); String jdbcUrl = "jdbc:TAOS://192.168.100.29:6030/log?user=root&password=taosdata"; connection = DriverManager.getConnection(jdbcUrl, connProps); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return connection; } }
【CreateDatabase.java】
创建数据的样例程序。
package com.rexel.tdengine.api; import com.rexel.tdengine.utils.TdUtils; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; /** * @ClassName CreateDatabase * @Description CreateDatabase * @Author: chunhui.qu * @Date: 2020/9/30 */ public class CreateDatabase { public static void main(String[] args) throws SQLException { TdUtils tdUtils = TdUtils.getInstance(); Connection conn = tdUtils.getConnection(); System.out.println("get connection"); Statement stmt = conn.createStatement(); stmt.executeUpdate("create database if not exists javatestdb"); System.out.println("create database"); stmt.executeUpdate("use javatestdb"); System.out.println("use database"); stmt.executeUpdate("create table if not exists javatesttable (ts timestamp, temperature int, humidity float)"); System.out.println("create table"); } }
【小插曲】
写完了测试代码,在执行的时候报错:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no taos in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at com.taosdata.jdbc.TSDBJNIConnector.<clinit>(TSDBJNIConnector.java:25) at com.taosdata.jdbc.TSDBDriver.connect(TSDBDriver.java:133) at java.sql.DriverManager.getConnection(DriverManager.java:664) at java.sql.DriverManager.getConnection(DriverManager.java:208) at com.rexel.tdengine.utils.TdUtils.getConnection(TdUtils.java:54) at com.rexel.tdengine.api.CreateDatabase.main(CreateDatabase.java:17) Disconnected from the target VM, address: ‘127.0.0.1:54954‘, transport: ‘socket‘
【解决过程】
重新看了一下官方文档,怀疑是没有安装Window客户端,尝试安装客户端程序。
安装文件:TDengine-client-2.0.4.0-Windows-x64.exe
重新执行程序之后,报了另一个错误:
java.sql.SQLException: TDengine Error: Invalid timestamp at com.taosdata.jdbc.TSDBJNIConnector.connect(TSDBJNIConnector.java:100) at com.taosdata.jdbc.TSDBConnection.connect(TSDBConnection.java:64) at com.taosdata.jdbc.TSDBConnection.<init>(TSDBConnection.java:56) at com.taosdata.jdbc.TSDBDriver.connect(TSDBDriver.java:135) at java.sql.DriverManager.getConnection(DriverManager.java:664) at java.sql.DriverManager.getConnection(DriverManager.java:208) at com.rexel.tdengine.utils.TdUtils.getConnection(TdUtils.java:54) at com.rexel.tdengine.api.CreateDatabase.main(CreateDatabase.java:17)
网友说可能是因为客户端的时间与服务器时间相差比较多的原因,
于是调整了服务器的时间。命令如下,调整之后,重启了一下服务器
修改系统时间:date --set "09/30/20 14:15" 系统时间向硬件同步:clock --show
重新运行程序,正确执行。感谢网友的帮助。
【感谢道友】
==聚合测试==
==压力测试==
==实际场景验证==
--END--
原文:https://www.cnblogs.com/quchunhui/p/13731825.html