背景:运行一个爬虫,开了10个线程,每个线程先去爬取指定数量的代理作为自己的代理池,然后开始工作。
问题:下面是爬虫日志的两行,可以看到在第一行任务处等待了45秒,而这里不过是输出一条信息,十分不理解为什么等了这么长时间?日志中像这样动辄十几秒什么一两分钟的情形基本都发生在爬取代理的过程中,是否意味着这个任务的代码有问题?
15:57:50 INFO Thread-2 the proxy already in list, skip
15:58:35 INFO Thread-10 {'https': '117.170.28.178:8123'} download 2111 bytes in 0.75 seconds(average in 1 tries), need 10, available count: 7
思考:我理解python的多线程调度机制是完成了一条指令后,就可以调用其他线程了,并不是一定要等着这个指令得到了预期的结果,那么如果我的代码写的有问题也不至于影响他的调度吧。这个线程没有进展又不将CPU的使用权让渡出来,GIL为什么不剥夺这个线程的运行时间,总不至于是在等待某个程序块或者函数运行完毕吧。
説明されている問題は、主に SQLite の不適切な使用によって引き起こされていることが判明しました。以前の設計では、エージェント プール内のすべてのエージェントの検証が完了し、一定数のエージェントがキャプチャされるまで接続が開かれてから閉じられました。エージェント情報を追加、変更、または削除すると、データ ファイルが書き込まれるため、粗粒度 SQLite が長時間ロックされます。
この問題を発見した後、新しい接続の開始時にインベントリ エージェントを読み取った後、すぐに接続を閉じました。その後、すべてのエージェントの新規データ、更新データ、および削除データは一時的にクラス変数に保存されます。必要なエージェントがすべて取得された後、新しい接続を開き、executemany でデータを更新してから接続を閉じ、スケジュールされたタスクを完了すると、速度が向上します。
しかし、元の状況では、スレッド スケジューリング メカニズムにより、データベースによってブロックされたスレッドが時間内に切り替えるのではなく、常にリソースを占有することができた理由がまだ理解できません。
あなたのスレッドはデータベースへの書き込みレベルでブロックされています。
3 つの方法を使用してsqlite
を使用しているので、データベースの書き込み操作を高速化するもう 1 つの古代の機能を提供しましょう。 リーリー書き込み速度を高速化します
sqlite
ディレクトリに放り込むことができます。これにより、ディスク I/O の影響が大幅に排除されます (メモリへの直接書き込みと同等)
tmpfs