Oracle 数据采集
简介
采集 Oracle 数据上报到 DataFlux 中
前置条件
- 已安装 Oracle 11g 及以上版本。
配置
对用户进行网络连接授权
使用 Oracle DBA 权限用户,sqlplus / as sysdba
。
为用户 testuser (假设用户已经存在)开通 UTL_HTTP
、DBMS_LOCK
、connect
权限,权限开通文档
传递参数时,注意 principal
的英文大小写问题,参数 host
为 DataWay 的 IP 地址。
GRANT CONNECT, RESOURCE TO testuser;
GRANT EXECUTE ON UTL_HTTP TO testuser;
GRANT EXECUTE ON DBMS_LOCK TO testuser;
BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
acl => 'test.xml',
description => 'data collection test',
principal => 'TESTUSER',
is_grant => true,
privilege => 'connect');
DBMS_NETWORK_ACL_ADMINI.ASSIGN_ACL (
acl => 'test.xml',
host => 'DataWayHost);
END;
/
创建数据表
登录到 Oracle testuser 用户,创建一张数据表用以绑定触发器。
CREATE TABLE serverinfo (
hostname varchar2(128),
ip varcahr2(16),
cpucore number );
INSERT INTO serverinfo (hostname, ip, cpucore) VALUES('ubuntu-db', '192.168.0.11', 4);
dataway发送函数
建立 HTTP 连接时,HOST 和 Header 要根据 dataway 文档进行填写。
UTL_HTTP.BEGIN_REQUEST()
的参数为 DataWay 的接收 URL,需要根据 DataWay 文档来进行配置
根据 DataWay 的文档,为 HTTP 添加对应的 Header;
调用
UTL_HTTP.WRITE_TEXT()
前,一定要先添加Content-Type
Header,否则接收方将无法获取有效的 body。注意顺序不能颠倒。
在触发器结束之前,需要调用
UTL_HTTP.END_RESPONSE()
释放连接,否则会造成连接资源的泄露。
CREATE OR REPLACE FUNCTION send_data(content IN VARCHAR2)
RETURN NUMBER
IS
requ UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
BEGIN
requ := UTL_HTTP.BEGIN_REQUEST('http://DataWayIP:PORT/v1/write/metrics?template=&token=&shortrp=&precision=ms');
UTL_HTTP.SET_HEADER(requ, 'User-Agent', 'test-agent');
UTL_HTTP.SET_HEADER(requ, 'X-Trace-Id', 'test-traceid');
UTL_HTTP.SET_HEADER(requ, 'X-Datakit-UUID', 'test-UUID');
UTL_HTTP.SET_HEADER(requ, 'X-Version', 'test-version');
UTL_HTTP.SET_HEADER(requ, 'Content-Length', LENGTHB(content));
ULT_HTTP.WRITE_TEXT(requ, content);
resp := UTL_HTTP.GET_RESPONSE(requ);
RETURN 0;
END;
创建触发器
触发器规则使用insert
,并绑定到第二步创建的数据表'serverinfo'。
行协议是 DataWay 接收数据的通用格式,包括Measurement
、Tag
、Field
和Timestamp
四个部分,格式如下:
weather,location=us-midwest temperature=82 1465839830100400200
| -------------------- -------------- |
| | | |
| | | |
+-----------+--------+-+---------+-+---------+
|measurement|,tag_set| |field_set| |timestamp|
+-----------+--------+-+---------+-+---------+
例如:serverinfo,hostname=macbook-pro ip="127.0.0.1",cpucore=8i 1582874030123
行协议文档,需要注意:
英文状态下逗号、双引号、等于号和空格都需要转义,在前面加转义字符
\
Field 的值如果是整型,需要在后面加个英文字符
i
,以示跟浮点型的区别,比如上面的cpucore
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT ON serverinfo
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION; -- 自制事务处理
jobid NUMBER;
time VARCHAR2;
content VARCHAR2;
BEGIN
-- 获取当前时间戳,单位是毫秒
SELECT (SYSDATE - TO_DATE('1970-1-1 8', 'YYYY-MM-DD HH24')) * 86400000 + TO_NUMBER(TO_CHAR(SYSTIMESTAMP(3), 'FF')) AS MILLIONS INTO time FROM DUAL;
-- 要发送的数据,行协议格式
content VARCHAR2(4096) := 'serverinfo,hostname='||:NEW.hostname||' ip="'||:NEW.ip||'",cpucore='||:NEW.cpucore||'i '||time||'\n';
-- 调用 send_data() 函数,提交到任务队列
DBMS_JOB.SUBMIT(jobid, 'exec declare out number; begin out := send_data(content); end;');
COMMIT;
END;
/
完成 Oracle 触发器的创建后,向 serverinfo
插入一条新数据。此时在数据的接收方(即 DataWay)将会收到数据并进行解析。
注意事项
DataWay 对应的接收路由如果开启 AK 验证(查看 DataWay 配置文件中是否开启),需要在 HTTP 请求添加 Authorization
Header,并进行大量的数据加密解密操作,PL/SQL 实现起来会相对困难,推荐使用 WDF(Web-Datakit-Framework)作为中间层。
即,Oracle 的数据发送到 WDF 后,由 WDF 进行 Header 添加、行协议转换、签名验证等操作,Oracle 只负责数据的发送,会大大减少触发器的复杂度。