1 背景

python 脚本跑数据, 其中有使用 urllib2 模块请求接口获取其他部门的数据.

使用方式为通过 id 循环获取接口数据.

import urllib2
import json
base_url = 'http://domain.com/api/modeCityPrice?id='
ids = [1, 2, 3]  # about 8000 items
for id in ids:
    req = urllib2.Request(base_url+str(id))
    response = urllib2.urlopen(req)
    ret = json.loads(response.read())
    response.close()

上面的代码是一个大致的过程, 在测试环境跑数据的时候是没问题的, 但是等到上线的时候就出了个大问题: 脚本跑了不到一半就除了异常 connection reset by peer

2 分析

  1. 刚开始搜索了一下, 发现有可能是没有加上 response.close , 但是加上之后还是报上面的异常.
  2. 查到了 stackoverflow 的一个问题 What does “connection reset by peer” mean? 类比一下, 就是对方的机器给我的 http 请求的 tcp 连接发了一个 RST 包, 然后 http 连接就断掉了.
  3. 于是我就想到了是否是 urllib2 的问题, 搜索了一下 urllib connection reset by peer 的相关数据, 找到了 v2ex 里面的一个帖子 urllib2 不支持 Connection:keep-alive?.
  4. 到这里原因就比较清楚了, 就是 urllib2 不支持 keep-alive 所以每次都会打开一个新的 http 请求, 而我们线上的接口是限制了 http 连接数的.

3 解决方案

  1. 增大 http 请求连接数 (改问题时, 运维不在身边, 而我又没有权限去改, Nginx 限制连接数与请求数)
  2. 幸好, 有另一种方案, 使用 requests 模块 Requests: HTTP for Humans

    r = requests.get(url=base_url+str(id))
    ret = r.json()
    

4 总结

  1. http 短连接有可能会耗尽服务器配置的 http 连接数
  2. python urllib2 这个模块过时了, 使用 requests 来代替
  3. 线上问题需要尽可能快的解决, 但是不能以损害身体为代价.

5 画外音

晚上 11 点回到住处, 抱着一个装满了薯片的箱子走进房间, kechikechi...

Last Updated 2017-05-11 四 10:15.
Render by hexo-renderer-org with Emacs 25.3.1 (Org mode 9.1.1)