Docker中Selenium爬虫插入Linode PostgreSQL时连接中断求助
解决PostgreSQL连接中途断开的问题
针对你遇到的偶发连接断开错误,结合你推测的爬取格式化耗时过长导致连接闲置被断开的情况,可以从以下几个方向解决:
1. 延迟获取数据库连接,避免闲置
不要在爬取数据前就建立数据库连接,而是等数据完全爬取并格式化完成后,再创建连接执行插入操作。如果使用连接池,配置合理的空闲连接回收机制,确保每次插入用的是活跃连接:
# 优化前:提前建立连接,长时间闲置导致断开 conn = await asyncpg.connect(your_dsn) data = await crawl_and_process_data() # 耗时操作,连接闲置 await conn.execute(...) # 优化后:数据准备好再拿连接 data = await crawl_and_process_data() async with asyncpg.connect(your_dsn) as conn: await conn.copy_records_to_table('your_table', records=data) # 或用连接池配置空闲超时 pool = await asyncpg.create_pool(your_dsn, max_idle_time=300) # 空闲5分钟自动回收 data = await crawl_and_process_data() async with pool.acquire() as conn: await conn.copy_records_to_table('your_table', records=data)
2. 调整PostgreSQL事务超时参数
检查PostgreSQL的idle_in_transaction_session_timeout参数,如果你的爬虫在事务中长时间闲置(比如爬取时事务未提交),PostgreSQL会主动断开连接。修改postgresql.conf:
idle_in_transaction_session_timeout = 300000 # 5分钟,单位毫秒
修改后重启PostgreSQL服务,同时确保插入操作完成后立即提交事务,不要让事务挂起。
3. 给插入操作添加重试逻辑
针对偶发的连接错误,捕获ConnectionDoesNotExistError等连接异常,添加重试机制:
import asyncpg from tenacity import retry, stop_after_attempt, retry_if_exception_type @retry(stop=stop_after_attempt(3), retry=retry_if_exception_type(asyncpg.exceptions.ConnectionDoesNotExistError)) async def insert_to_db(data): async with asyncpg.connect(your_dsn) as conn: await conn.copy_records_to_table('your_table', records=data) await conn.commit() # 调用方式 data = await crawl_and_process_data() await insert_to_db(data)
4. 检查网络层的空闲超时设置
- Linode防火墙:登录Linode控制台,查看防火墙的空闲连接超时时间,确保它大于你设置的
tcp_keepalives_idle(比如设为10分钟),避免防火墙主动断开闲置连接。 - Docker网络:调整Docker的连接跟踪超时参数,防止NAT层断开连接:
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=600
要永久生效,将参数写入/etc/sysctl.conf文件。
5. 解耦爬取与插入流程
把爬取、格式化和数据库插入拆成独立环节,用消息队列(如Redis)做中间件:
- 爬虫服务:只负责爬取数据并格式化,将结果存入Redis队列
- 插入服务:独立运行,从Redis队列中取出数据,批量插入PostgreSQL
这样爬取的耗时不会占用数据库连接,插入服务可以维持稳定的连接池,彻底避免闲置断开问题。
内容的提问来源于stack exchange,提问作者internn00b
相关产品推荐
相关产品推荐

