Logstash JDBC输入重试参数不生效 无法自动重连数据库如何解决
问题背景
- 当前使用Logstash实现PostgreSQL到MySQL的数据同步,
/etc/logstash/conf.d目录下存放10份同步配置,通过systemctl start logstash将Logstash作为系统服务启动 - 已在JDBC输入块中配置重试参数
connection_retry_attempts => 10、connection_retry_attempts_wait_time => 120,预期效果为每2分钟重试1次,最多重试10次,配置示例如下:
input { jdbc { jdbc_driver_library => "/etc/logstash/lib/postgresql-42.2.14.jar" jdbc_driver_class => "org.postgresql.Driver" jdbc_paging_enabled => true jdbc_page_size => "50000" connection_retry_attempts => 10 connection_retry_attempts_wait_time => 120 jdbc_connection_string => "jdbc:postgresql://xxx/xxx" jdbc_user => "user" jdbc_password => "xxx" jdbc_default_timezone => "UTC" statement => "select ... from ... where ... and login_time >= :sql_last_value " tracking_column => "login_time" tracking_column_type => "timestamp" use_column_value => true last_run_metadata_path => "/home/data/logs/..." schedule => "* * * * *" type => "xxx" } }
- 实际运行异常:一次数据库连接错误发生后,10个表的同步任务有8个停止运行,仅2个正常工作,重启Logstash服务后同步恢复。查看日志未看到失败任务的重试操作记录,异常日志片段如下:
[2022-06-07T18:08:03,763][ERROR][logstash.inputs.jdbc ][main] Unable to connect to database. Trying again {:error_message=>"Java::OrgPostgresqlUtil::PSQLException: The connection attempt failed."} [2022-06-07T18:10:03,914][INFO ][logstash.inputs.jdbc ][main] (0.015812s) SELECT CAST(current_setting('server_version_num') AS integer) AS v [2022-06-07T18:10:03,940][INFO ][logstash.inputs.jdbc ][main] (0.024598s) SELECT count(*) AS "count" FROM (select * from xxx where added_time >= '2022-06-06 11:47:00' and added_time >= '2022-06-07 10:06:48.221000+0000' ) AS "t1" LIMIT 1
问题原因
当前配置的两个重试参数仅作用于插件初始化阶段的首次连接尝试,不会覆盖调度运行过程中出现的连接异常:
- Logstash JDBC输入插件启动时,会先尝试建立数据库连接,这一阶段触发连接错误时,才会按照
connection_retry_attempts和connection_retry_attempts_wait_time的配置执行重试 - 插件完成初始化、进入每分钟一次的定时调度周期后,如果单次调度执行SQL时出现连接断开、连接失败的问题,旧版本插件不会自动触发重试逻辑,而是直接将该次调度标记为失败,等待进入下一个调度周期;如果异常导致插件运行线程终止,对应的同步任务就会直接停止,不会自行恢复。日志中连接报错2分钟后出现的正常SQL执行记录,实际是未受异常影响的2个任务的运行日志,并非失败任务的重试记录
- 旧版本JDBC插件存在已知bug:重试逻辑的异常捕获范围不全,部分PostgreSQL驱动抛出的连接异常不会被重试逻辑识别,会直接导致插件线程退出,这也是看不到后续重试日志的核心原因。
配置方案
按以下顺序调整配置即可实现稳定的连接自动重试:
1. 升级JDBC输入插件版本
将logstash-integration-jdbc插件升级到5.2.0及以上版本,该版本修复了调度阶段连接异常不重试、异常捕获范围不全的问题,升级完成后原有connection_retry_attempts和connection_retry_attempts_wait_time参数会同时覆盖初始化阶段和调度运行阶段的连接异常重试。执行以下命令完成升级:
/usr/share/logstash/bin/logstash-plugin update logstash-integration-jdbc
2. 补充JDBC连接串的内置重试参数
PostgreSQL JDBC驱动本身自带连接重试能力,在JDBC连接串末尾追加参数,从驱动层兜底重试逻辑,避免插件层重试失效:
jdbc_connection_string => "jdbc:postgresql://xxx/xxx?loginTimeout=30&connectTimeout=30&socketTimeout=120&tcpKeepAlive=true&reWriteBatchedInserts=true&autosave=always"
参数说明:
loginTimeout、connectTimeout:限制连接建立超时时间,避免长时间无响应挂住线程socketTimeout:限制socket读取超时时间,防止死连接占用任务线程tcpKeepAlive:开启TCP心跳,提前识别断开的无效连接autosave=always:连接异常恢复后自动恢复会话状态,避免事务状态异常导致SQL执行失败
3. 配置Logstash全局进程异常自愈
修改Logstash服务配置,开启管道异常自动重启,避免个别任务线程退出导致同步任务永久停止:
编辑/etc/logstash/logstash.yml配置文件,添加/修改以下参数:
pipeline.workers: 2 pipeline.batch.size: 125 pipeline.batch.delay: 50 pipeline.ordered: auto # 开启管道异常自动重载 pipeline.reloadable: true pipeline.reload.interval: 30s # 配置死信队列避免数据丢失 dead_letter_queue.enable: true path.dead_letter_queue: /var/lib/logstash/dead_letter_queue
如果是单配置文件对应单管道的部署模式,建议为每个同步任务在pipelines.yml中配置独立管道,单个任务异常退出不会影响其他同步任务运行。
4. 补充系统层面的服务兜底
配置systemd服务自动重启,极端情况下Logstash进程异常退出时可以自动拉起:
编辑/etc/systemd/system/logstash.service文件,在[Service]段添加以下配置:
Restart=always RestartSec=60 StartLimitInterval=0
执行systemctl daemon-reload重载配置后生效。
验证方式
配置调整完成后重启Logstash服务,手动模拟PostgreSQL连接断开(比如临时封禁PG端口、重启PG服务),观察日志:
- 连接异常发生后会按配置的2分钟间隔打印重试日志
- 最多重试10次,重试期间任务不会停止
- 连接恢复后同步任务自动恢复运行,不需要手动重启服务
内容的提问来源于stack exchange,提问作者user2894829

