Python - 将随机数与多线程一起使用



我正在使用python 2和请求。这个问题更多的是好奇我如何提高这种性能。

现在的问题是,我必须在请求的标头中将加密签名发送到HTTPS服务器。此签名包括一个"nonce",它必须是时间戳,并且必须始终增加(在服务器端(。

显然,这可能会对在多个线程上运行多个HTTP会话造成严重破坏。请求最终没有按顺序发送,因为它们在生成标头和发送HTTPS POST请求之间被中断。

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

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

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

听起来请求库不支持异步发送。

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

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

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

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

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

即使您决定添加一个依赖项,以便在发送标头后释放锁,您仍然可能会发现偶尔会遇到计时问题。带有标头的消息数据包在到达服务器的途中可能会延迟。

最新更新