该帖子有点长哈...不好意思🤪
是这样,这是一个爬虫项目的主程序入口,下面代码里面的 mongo_connection = mongo_connect( connect = False, server_selection_timeoutMS = 60000 )
用来连接数据库,但我在服务器上测试的时候发现一直提示 timeout 报错(详见上面的报错信息)
我查了不少文章,看到不少说是要在多进程开启后再给每一个进程连接 mongoDB ,所以一开始我将连接数据库的代码放到了三个爬取程序的开头(就是下文那三个 parser() 函数),但依旧报同样的错; 然后我在 GitHub 上面看到了一个关于多进程下 Pymongo 提示 UserWarning 的解答,里面提到了可以添加 connect = False 参数,但我试过还是不行,应该问题也不在这里; 然后我又修改了 serverSelectionTimeoutMS ,将时间改为 60 秒(嗯当然还是没用)
求大佬指点一下怎么在使用 concurrent.futures 开启多进程的情况下连接 mongoDB🙏🏽🙏🏽🙏🏽!谢谢!
下面贴了环境、报错信息和代码
CentOS 7.8.2003
python = 3.7.7
依赖包版本:
pymongo == 4.0.1
concurrent:Python 自带
该信息来源于日志
ERROR: 192.168.1.202:27017: timed out, Timeout: 60.0s, Topology Description: <TopologyDescription id: 622086a8ea6efc1d07de056f, topology_type: Unknown, servers: [<ServerDescription ('192.168.1.202', 27017) server_type: Unknown, rtt: None, error=NetworkTimeout('192.168.1.202:27017: timed out')>]>
import pymongo
from concurrent.futures import PoolProcessExecutor, as_completed
# 导入外部自定义模块
import ...
def run_spider(log_recorder, proxy):
"""
主程序,可启动目标网页的爬取程序
:param log_recorder: 日志记录工具
:param proxy: 项目专用代理
:return:
"""
log_recorder.info( "Spider starts running! :)" )
try:
# 连接数据库
mongo_connection = mongo_connect( connect = False, server_selection_timeoutMS = 60000 )
try:
# 主程序运行
council_parser( mongo_connection, log_recorder, proxy )
gd_province_parser( mongo_connection, log_recorder, proxy )
market_supervisor_parser( mongo_connection, log_recorder, proxy )
log_recorder.info( "Spider ran over! :)" )
# 爬取结束后断开数据库连接
mongo_connection.close()
except Exception as e:
log_recorder.error(f"{e} :(")
# 出现异常依然断开连接
mongo_connection.close()
except Exception as e:
log_recorder.error(f"{e}:(")
if __name__ == "__main__":
# 设置日志工具
regulation_logger = spiderLogger.get_logger('regulation')
# 设置代理
proxy = get_proxy()
# 多进程并发
with ProcessPoolExecutor(max_workers = 8) as executor:
fs = []
futures = executor.submit(run_spider, regulation_logger, proxy)
fs.append(futures)
for future in as_completed(fs):
result = future.result()
mongo_connent方法代码:
def mongo_connect(connect = True, server_selection_timeoutMS: int = 60000):
mongo_connection = MongoClient(
server = settings.DATABASES['mongodb']['HOST'],
port = settings.DATABASES['mongodb']['PORT'],
username = settings.DATABASES['mongodb']['USER'],
password = settings.DATABASES['mongodb']['PASSWORD'],
db = settings.DATABASES['mongodb']['db'],
connect = connect,
serverSelectionTimeoutMS = server_selection_timeoutMS
)
return mongo_connection
1
fgwmlhdkkkw 2022-03-03 18:24:51 +08:00
……你用命令行能连上数据库吗?
|
2
DesmondLeo OP @fgwmlhdkkkw 命令行可以
|
3
vvhhaaattt 2022-03-03 18:54:43 +08:00 via Android
我觉得先确认你不用多进程时,代码能正常连接不。
|
4
ClericPy 2022-03-03 23:01:38 +08:00
1. mongo_connect 哪来的有点陌生, 这东西不好调试的话临时闭包到 run_spider 里测试一下? 怀疑有些变量传递到进程里面有地方不太对, 多进程类似于各种并行计算的一个特点就是: 尽量无状态无副作用, 里面的各种依赖 /参数 /上下文都尽量隔离干净
2. 本地调试可以运行但线上不行的话, 可能的地方特别多(难怪虚拟化和 go 那么火了) 2.1 最大可能是网络本身就不通(防火墙规则啊, 网卡 ip 不对啊, 非局域网啊, 非开放端口啊), 但是如果关了多进程会 ok, 网络应该不是问题. 可以临时把 PoolProcessExecutor 改成多线程那个, 反正接口一样的, 而且爬虫这玩意本来就没必要多进程 2.2 Python 版本有区别, 个别底层依赖有差异, 这个少见但也遇到过 2.3 第三方依赖的版本或者 C 依赖有差异, 尽量排除这种情况, 以前我遇到过类似情况, 换个版本居然就通了 2.4 检查是不是每个进程都超时, 有一定可能是程序里面或者 mongodb 那边有奇怪的死锁 |
5
ch2 2022-03-03 23:30:34 +08:00 via iPhone
你都没有指定 host 跟 port ,让它去连啥啊
|
6
dudu2017 2022-03-03 23:52:41 +08:00
mongo_connect 方法是你自己封装的吧,这里的代码是不是也应该贴一下?
|
7
DesmondLeo OP @vvhhaaattt 不用的时候可以
|
8
DesmondLeo OP |
9
DesmondLeo OP @ClericPy 啊好详细的回复😃,我昨天后来在排查的时候感觉应该是死锁(感觉),那个 ThreadProcessExecutor 昨天我也试过了,效果一样 2333 ,应该不是这个问题,我今天再看看怎么处理
|