python进程池如何复用_python进程池加线程池的一些问题

使用进程池加多线程的情况可以合理利用cpu,但是 会有些问题:

from multiprocessing import Pool

import threading

import requests

def test1():

s=requests.Session()#使用连接池访问,共用io复用

for i in range(10000):

try:

rep=s.get("http://www.163.com/")

print "test1"

except:

continue

def test2():

s=requests.Session()

for i in range(10000):

try:

rep=s.get("http://www.126.com/")

print "test2"

except:

continue

def coroutine():

t1 = threading.Thread(target=test1)

t2 = threading.Thread(target=test2)

t1.start()

t2.start()

t1.join()

t2.join()

if __name__=="__main__":

p=Pool()

for i in range(4):

p.apply_async(coroutine,args=())#使用非阻塞访问,主进程不阻塞,继续执行

p.close()

p.join()

上面有几个坑,

首先看下线程树:

python(16884)─┬─python(16889)─┬─{python}(16896)

│ └─{python}(16898)

├─python(16890)─┬─{python}(16897)

│ └─{python}(16899)

├─python(16891)─┬─{python}(16900)

│ └─{python}(16901)

├─python(16892)─┬─{python}(16902)

│ └─{python}(16903)

├─{python}(16893)

├─{python}(16894)

└─{python}(16895)

第一个是 ,不使用io复用,或者说,不使用requests的seesion,保持长连接的话, 使用strace抓包如下:

root@wan-ThinkPad-E450c:/home/wan/ceshi# strace -p 28501 -e trace=connect

strace: Process 28501 attached

connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.1.1")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.132.121")}, 16) = 0

connect(6, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.47")}, 16) = 0

connect(6, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.48")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.132.121")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.1.1")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.48")}, 16) = 0

connect(6, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.132.121")}, 16) = 0

connect(6, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.47")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.48")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.1.1")}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.47")}, 16) = 0

connect(6, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.214.133.48")}, 16) = 0

connect(6, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0

connect(6, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("183.

每个线程会疯狂的创建连接,这里,有可能耗尽连接。

第二个,这里是否有类似pipeline的方式,批量发请求,针对数据库。

第三个,这里ctrl +c 已经不能正常退出了。使用join会挂起主进程,而信号只有主进程能接受,而join后的主进程,根本就接受不到。

有些比较大的程序,比如datadog,通常做法是启动时,将pid写到pid文件中,程序响应stop的时候,去pid文件中取pid,然后kill 掉自身。

还有种思路是:设置子线程为daemon线程,启动子线程后主线程调用is_Alive的方法手动模拟join过程。

最后,其实靠ctrc+c的方式stop,并不是很常见的做法,一般将主进程写成守护进程。

第四个,是没超时控制,比如watchdog的方式,控制重启进程池。

第五个,如果kill掉主进程,会使子进程成为孤儿进程。设置Daemon关键字可以使主进程退出时子进程一起退出。

第六个,这里输出是stdio,而生产中是输出到log,要考虑多进程,线程日志同步的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值