一、问题描述
Flink 1.16.0 + OceanBase-cdc-2.3 编写table sql使用initial模式采集OceanBase库百万级表出现以下问题:
二、定位具体问题
通过截图可以很容易看到,是读取出现了超时问题。之前采集过几千、几万条的小表并没有报这个错误,都是一样的代码,所以可以直接定位到问题原因在读取数据阶段。首先下面进行排查
- 第一步核对OceanBase-cdc相关配置信息
"'username' = 'xxxxxx'," +
"'password' = 'xxxxxx'," +
"'hostname' = 'xxxxxx'," +
"'port' = 'xxxxxx'," +
"'rootserver-list' = 'xxxxxx',"+
"'logproxy.host' = 'xxxxxx'," +
"'logproxy.port' = 'xxxxxx"
如果以配置没有问题,就要看下报错位置,通过错误提示找到抛出异常位置,在OceanBase-cdc的jar包源码中查看如下:
这里查看源码,看到有this.connectTimeout.get…信息,这说读取超过这个timeout时间没有读取完就会抛出此异常。继续点击找到了具体connectTimeout信息:
三、问题解决
结合Flink-cdc 2.3版本的官方文档,发现在OceanBase-cdc-2.3版本新增加了刚才查到的connect.timeout字段,如下图所示(第一张为2.2版本,第二张为2.3版本)
可以看到第二张图红框中,2.3版本新增加的connect.timeout字段,不做配置的话默认30s。如果只看2.3 版本OceanBases-cdc sql样例的话,可能根本不会在意这个字段,所以看文档一定要看完整,不要拿来例子就用,一定要清楚所有配置项的描述。下面是官方样例,并没有加入此字段:
-- 在 Flink SQL 中创建 OceanBase 表 `orders`
Flink SQL> CREATE TABLE orders (
order_id INT,
order_date TIMESTAMP(0),
customer_name STRING,
price DECIMAL(10, 5),
product_id INT,
order_status BOOLEAN,
PRIMARY KEY (order_id) NOT ENFORCED
) WITH (
'connector' = 'oceanbase-cdc',
'scan.startup.mode' = 'initial',
'username' = 'user@test_tenant',
'password' = 'pswd',
'tenant-name' = 'test_tenant',
'database-name' = 'test_db',
'table-name' = 'orders',
'hostname' = '127.0.0.1',
'port' = '2881',
'rootserver-list' = '127.0.0.1:2882:2881',
'logproxy.host' = '127.0.0.1',
'logproxy.port' = '2983');
-- 从表 orders 中读取快照数据和 binlog 数据
Flink SQL> SELECT * FROM orders;
回到源码中,找到解析connect.timeout的代码,发现不做配置默认时间(Duration.ofSeconds(30L))也就是30s
注意,代码中的默认值是通过**ofSeconds(30L)**方法解析的30s是30L,但我们在connect.timeout中的数值是durationType()解析的毫秒级数值,所以配置的时候要注意,**connect.timeout=‘30000’**是30s,不要直接写300以为是5分钟其实是300ms,要不然flink任务会直接爆炸,已踩坑0.0。
最终,在sql中添加OceanBase-cdc配置信息:connect.timeout=‘300000’(5分钟),问题得以解决,程序正常运行,数据也成功获取。以官方文档为例,添加后如下:
-- 在 Flink SQL 中创建 OceanBase 表 `orders`
Flink SQL> CREATE TABLE orders (
order_id INT,
order_date TIMESTAMP(0),
customer_name STRING,
price DECIMAL(10, 5),
product_id INT,
order_status BOOLEAN,
PRIMARY KEY (order_id) NOT ENFORCED
) WITH (
'connector' = 'oceanbase-cdc',
'scan.startup.mode' = 'initial',
'username' = 'user@test_tenant',
'password' = 'pswd',
'tenant-name' = 'test_tenant',
'database-name' = 'test_db',
'table-name' = 'orders',
'hostname' = '127.0.0.1',
'port' = '2881',
'connect.timeout'='300000'
'rootserver-list' = '127.0.0.1:2882:2881',
'logproxy.host' = '127.0.0.1',
'logproxy.port' = '2983');
-- 从表 orders 中读取快照数据和 binlog 数据
Flink SQL> SELECT * FROM orders;
四、总结
只要思想不滑坡,办法总比困难多!