dan*_*360 4 python unix performance http task
我有一个python脚本,它会向各个域发出大量的HTTP和urllib请求.
我们有大量的域进程,需要尽快完成.由于HTTP请求很慢(即它们可能超出域上没有网站),我会在任何时候运行一些脚本,从数据库中的域列表中提取它们.
我看到的问题是在一段时间内(几小时到24小时)脚本都开始变慢,ps -al显示它们正在睡觉.
服务器功能非常强大(8核,72GB RAM,6TB Raid 6等80MB 2:1连接)并且永远不会超出,即Free -m显示
-/+ buffers/cache: 61157 11337
Swap: 4510 195 4315
Run Code Online (Sandbox Code Playgroud)
顶部显示80-90%闲置
sar -d显示平均5.3%的效用
更有趣的是,iptraf以大约50-60MB/s的速度开始,大约4小时后最终达到8-10MB/s.
我目前在每台服务器(2台服务器)上运行大约500个版本的脚本,它们都显示相同的问题.
ps -al 显示大多数python脚本正在睡觉,我不明白为什么例如:
0 S 0 28668 2987 0 80 0 - 71003 sk_wai pts/2 00:00:03 python
0 S 0 28669 2987 0 80 0 - 71619 inet_s pts/2 00:00:31 python
0 S 0 28670 2987 0 80 0 - 70947 sk_wai pts/2 00:00:07 python
0 S 0 28671 2987 0 80 0 - 71609 poll_s pts/2 00:00:29 python
0 S 0 28672 2987 0 80 0 - 71944 poll_s pts/2 00:00:31 python
0 S 0 28673 2987 0 80 0 - 71606 poll_s pts/2 00:00:26 python
0 S 0 28674 2987 0 80 0 - 71425 poll_s pts/2 00:00:20 python
0 S 0 28675 2987 0 80 0 - 70964 sk_wai pts/2 00:00:01 python
0 S 0 28676 2987 0 80 0 - 71205 inet_s pts/2 00:00:19 python
0 S 0 28677 2987 0 80 0 - 71610 inet_s pts/2 00:00:21 python
0 S 0 28678 2987 0 80 0 - 71491 inet_s pts/2 00:00:22 python
Run Code Online (Sandbox Code Playgroud)
脚本中没有睡眠状态被执行,所以我无法理解为什么ps -al显示大多数睡眠状态以及为什么当CPU,内存,磁盘访问和带宽为时,它们应该越来越慢,从而减少IP请求的时间.所有可用的丰富.
如果有人可以提供帮助,我将非常感激.
编辑:
代码是巨大的,因为我通过它使用异常来捕获有关域的诊断,即我无法连接的原因.如果需要,可以在某处发布代码,但是通过HTTPLib和URLLib的基本调用是直接的python示例.
更多信息:
都
quota -u mysql quota -u root
一无所获
nlimit -n返回1024有更改limit.conf允许mysql允许16000软和硬连接,并且能够运行超过2000脚本到目前为止,但仍然是问题.
好吧,所以我已经改变了用户的所有限制,确保所有套接字都关闭(它们没有),虽然情况比较好,但我仍然慢下来虽然没有那么糟糕.
有趣的是,我也注意到了一些内存泄漏 - 脚本运行的时间越长,内存越多,但我不确定是什么导致这种情况.我将输出数据存储在一个字符串中,然后在每次迭代后将其打印到终端,我也在最后清除字符串,但是不断增加的内存可以降低到存储所有输出的终端吗?
编辑:似乎没有 - 跑出30个脚本而没有输出到终端,仍然是相同的泄漏.我没有使用任何聪明的东西(只是字符串,HTTPlib和URLLib) - 想知道python mysql连接器是否有任何问题......?
检查ulimit并quota选择框和运行脚本的用户. /etc/security/limits.conf也可能包含您可能想要修改的资源限制.
ulimit -n 将显示允许的最大打开文件描述符数.
您还可以检查fd,ls -l /proc/[PID]/fd/其中[PID]一个脚本的进程ID 在哪里.
需要看一些代码来说明真正发生的事情..
编辑(导入评论和更多故障排除想法):
你能显示打开和关闭连接的代码吗?
刚运行一些脚本进程时,它们是否也会在一段时间后开始闲置?或者只有当有几百个+一次运行时才发生这种情况?
是否有单个父进程启动所有这些脚本?
如果您使用s = urllib2.urlopen(someURL),请确保s.close()完成后再使用它.Python 通常可以为你关闭事情(比如你做的事情x = urllib2.urlopen(someURL).read()),但如果你被告知(例如将变量赋值给返回值),它会留给你.urlopen().仔细检查urllib调用的打开和关闭(或所有 I/O代码是否安全).如果每个脚本被设计为一次只有一个打开的套接字,并且/proc/PID/fd每个脚本进程显示多个活动/打开套接字,那么肯定有一个代码问题需要修复.
ulimit -n显示1024被给予限制开放的插座/ FD的是,MySQL的用户都可以有,你可以改变这个ulimit -S -n [LIMIT_#],但首先看看这篇文章:
用"的ulimit -n"更改的process.max-文件描述符会导致MySQL来改变table_open_cache值.
您可能需要注销并重新封装.和/或将其添加到/etc/bashrc(source /etc/bashrc如果您更改bashrc并且不想注销/中,请不要忘记).
磁盘空间是我发现的另一件事(困难的方式)会导致非常奇怪的问题.我的进程就像它们正在运行(没有被僵尸)但没有做到预期的,因为它们在没有磁盘空间的分区上有一个日志文件的打开句柄.
netstat -anpTee | grep -i mysql 还将显示这些插座是否已连接/建立/等待关闭/等待超时/等.
watch -n 0.1 'netstat -anpTee | grep -i mysql'在一个漂亮的表输出中实时查看套接字打开/关闭/更改状态/ etc (export GREP_OPTIONS=如果你将它设置为类似的话可能需要首先--color=always).
lsof -u mysql或者lsof -U还会显示你打开的FD(输出非常详细).
import urllib2
import socket
socket.settimeout(15)
# or settimeout(0) for non-blocking:
#In non-blocking mode (blocking is the default), if a recv() call
# doesn’t find any data, or if a send() call can’t
# immediately dispose of the data,
# a error exception is raised.
#......
try:
s = urllib2.urlopen(some_url)
# do stuff with s like s.read(), s.headers, etc..
except (HTTPError, etcError):
# myLogger.exception("Error opening: %s!", some_url)
finally:
try:
s.close()
# del s - although, I don't know if deleting s will help things any.
except:
pass
Run Code Online (Sandbox Code Playgroud)
一些手册页和参考链接:
| 归档时间: |
|
| 查看次数: |
2311 次 |
| 最近记录: |