Python - 使用带有多线程的nonce

时间:2016-02-03 17:12:00

标签: python multithreading python-2.7 python-requests

我正在使用python 2请求。这个问题更像是对如何改善这种表现的好奇心。

现在的问题是我必须在请求的标头中向HTTPS服务器发送加密签名。此签名包括" nonce"必须是时间戳,并且总是必须增加(在服务器端)。

显然,这会对在多个线程上运行多个HTTP会话造成严重破坏。由于在生成标头和发送HTTPS POST请求之间中断,请求最终不按顺序发送。

解决方案是在创建签名之前锁定线程,直到收到HTTPS数据结束。理想情况下,我想在HTTP请求为SENT后释放LOCK,而不必等待收到数据。在HTTP标头是SENT之后,有没有办法可以使用请求释放锁定?请参阅代码示例:

self.lock是一个Threading.Lock。此类(self)的这个实例在多个Threads之间共享。

def get_nonce(self):
    return int(1000*time.time())

def do_post_request(self, endpoint, parameters):
    with self.lock:
        url = self.base + endpoint
        urlpath = endpoint
        parameters['nonce'] = self.get_nonce()
        postdata = urllib.urlencode(parameters)
        message = urlpath + hashlib.sha256(str(parameters['nonce']) + postdata).digest()
        signature = hmac.new(base64.b64decode(self.secret_key), message, hashlib.sha512)
        headers = {
            'API-Key': self.api_key,
            'API-Sign': base64.b64encode(signature.digest())
        }
        data = urllib.urlencode(parameters)
        response = requests.post(url, data=data, headers=headers, verify=True).json()

    return response

1 个答案:

答案 0 :(得分:2)

听起来像请求库doesn't have any support是异步发送的。

  

使用默认传输适配器,请求不提供任何类型的非阻塞IO。 Response.content属性将阻塞,直到下载完整个响应。如果您需要更多粒度,则库的流式传输功能(请参阅流式传输请求)允许您一次检索较小数量的响应。但是,这些调用仍会阻止。

     

如果您担心使用阻塞IO,那么有很多项目将Requests与Python的异步框架结合起来。两个很好的例子是问候和请求期货。

我在评论中看到您在添加更多依赖项时犹豫不决,因此我唯一的建议是:

  • 当你的nonce被拒绝时添加重试逻辑。这似乎是最pythonic的解决方案,只要nonce不被经常拒绝,它应该可以正常工作。
  • 限制nonce发生器。保留用于前一个nonce的时间戳,如果在请求下一个nonce时已经足够长,则保持睡眠状态。
  • 批量处理邮件。如果协议允许,您可能会发现当您添加延迟以等待其他消息并将其作为批处理发送时,吞吐量实际上会上升。
  • 更改服务器,以便nonce值不必增加。如果您控制服务器,使消息彼此独立将为您提供更灵活的协议。
  • 使用会话池。我猜测nonce值只需要在一个会话中增加。如果您创建一个线程池并让每个线程都打开自己的会话,那么您仍然可以获得合理的吞吐量,而不会出现当前的时序问题。

显然,您必须衡量进行这些更改的效果。

即使你决定添加一个依赖项,让你在发送标题后释放锁定,你仍然可能会发现偶尔会出现计时问题。带有标题的消息包可能会在去往服务器的路上被延迟。