Boto S3偶尔抛出httplib.IncompleteRead

wol*_*lak 9 python amazon-s3 boto

我有几个守护进程使用boto从Amazon S3读取许多文件.每隔几天,我就遇到了一个从深入的boto中抛出httplib.IncompleteRead的情况.如果我尝试重试请求,它会立即失败并使用另一个IncompleteRead.即使我打电话bucket.connection.close(),所有进一步的请求仍然会出错.

我觉得我可能偶然发现了这里的boto中的一个bug,但似乎没有其他人能够击中它.难道我做错了什么?所有的守护进程都是单线程的,我试过设置is_secure两种方式.

Traceback (most recent call last):
  ...
  File "<file_wrapper.py",> line 22, in next
    line = self.readline()
  File "<file_wrapper.py",> line 37, in readline
    data = self.fh.read(self.buffer_size)
  File "<virtualenv/lib/python2.6/site-packages/boto/s3/key.py",> line 378, in read
    self.close()
  File "<virtualenv/lib/python2.6/site-packages/boto/s3/key.py",> line 349, in close
    self.resp.read()
  File "<virtualenv/lib/python2.6/site-packages/boto/connection.py",> line 411, in read
    self._cached_response = httplib.HTTPResponse.read(self)
  File "/usr/lib/python2.6/httplib.py", line 529, in read
    s = self._safe_read(self.length)
  File "/usr/lib/python2.6/httplib.py", line 621, in _safe_read
    raise IncompleteRead(''.join(s), amt)
Run Code Online (Sandbox Code Playgroud)

环境:

  • 亚马逊EC2
  • Ubuntu 11.10
  • Python 2.6.7
  • 博托2.12.0

shx*_*hx2 5

我已经为这个问题苦苦挣扎了一段时间,运行长时间运行的进程,从 S3 读取大量数据。我决定在这里发布我的解决方案,供后代使用。

首先,我确信 @Glenn 指出的黑客行为有效,但我选择不使用它,因为我认为它具有侵入性(黑客攻击 httplib)并且不安全(它盲目地返回它所得到的内容,即,尽管return e.partial事实上它可以是真实错误情况)。

这是我最终想出的解决方案,它似乎有效。

我正在使用这个通用重试函数:

import time, logging, httplib, socket

def run_with_retries(func, num_retries, sleep = None, exception_types = Exception, on_retry = None):
    for i in range(num_retries):
        try:
            return func()  # call the function
        except exception_types, e:
            # failed on the known exception
            if i == num_retries - 1:
                raise  # this was the last attempt. reraise
            logging.warning(f'operation {func} failed with error {e}. will retry {num_retries-i-1} more times')
            if on_retry is not None:
                on_retry()
            if sleep is not None:
                time.sleep(sleep)
    assert 0  # should not reach this point
Run Code Online (Sandbox Code Playgroud)

现在,当从 S3 读取文件时,我正在使用此函数,该函数会在出现IncompleteRead错误时在内部执行重试。出现错误时,在重试之前,我会调用key.close().

def read_s3_file(key):
    """
    Reads the entire contents of a file on S3.
    @param key: a boto.s3.key.Key instance
    """
    return run_with_retries(
        key.read, num_retries = 3, sleep = 0.5,
        exception_types = (httplib.IncompleteRead, socket.error),
        # close the connection before retrying
        on_retry = lambda: key.close()
    )
Run Code Online (Sandbox Code Playgroud)


小智 4

这很可能是 boto 中的一个错误,但您描述的症状并不是它独有的。看

使用 httplib 进行不完整读取

https://dev.twitter.com/discussions/9554

由于 httplib 出现在您的回溯中,因此这里提出了一种解决方案:

http://bobrochel.blogspot.in/2010/11/bad-servers-chunked-encoding-and.html?showComment=1358777800048

免责声明:我没有 boto 的经验。这仅基于研究并发布,因为没有其他回应。