Python-将nonce与多线程结合使用

Python-将nonce与多线程结合使用,python,multithreading,python-2.7,python-requests,Python,Multithreading,Python 2.7,Python Requests,我正在使用Python2处理请求。这个问题更多的是我对如何提高这种性能的好奇 现在的问题是,我必须在请求头中将加密签名发送到HTTPS服务器。此签名包括一个“nonce”,它必须是时间戳,并且必须始终增加(在服务器端) 显然,这会对在多个线程上运行多个HTTP会话造成严重破坏。由于在生成标头和发送HTTPS POST请求之间被中断,请求最终被不按顺序发送出去 解决方案是在创建签名之前锁定线程,直到接收HTTPS数据结束。理想情况下,我希望在发送HTTP请求后释放锁,而不必等待接收数据。在发送HT

我正在使用Python2处理请求。这个问题更多的是我对如何提高这种性能的好奇

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

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

解决方案是在创建签名之前锁定线程,直到接收HTTPS数据结束。理想情况下,我希望在发送HTTP请求后释放锁,而不必等待接收数据。在发送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的使用,那么有很多项目将请求与Python的异步框架结合起来。两个很好的例子是grequests和requests

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

  • 当您的nonce被拒绝时添加重试逻辑。这似乎是最具python风格的解决方案,只要nonce不经常被拒绝,它就可以正常工作
  • 对当前生成器进行节流。保留前一个nonce使用的时间戳,如果在请求下一个nonce时时间不够长,则休眠
  • 批处理消息。如果协议允许,当您添加等待其他消息的延迟并将其作为批发送时,您可能会发现吞吐量实际上会增加
  • 更改服务器,使nonce值不必增加。如果您控制服务器,使消息相互独立将为您提供更灵活的协议
  • 使用会话池。我猜nonce值只需要在单个会话中增加。如果您创建一个线程池并让每个线程打开自己的会话,那么您仍然可以获得合理的吞吐量,而不会出现当前的计时问题
显然,您必须衡量进行这些更改的性能结果


即使您决定添加一个依赖项,允许您在发送头之后释放锁,您仍然可能会发现偶尔会出现计时问题。带有标题的消息包在发送到服务器的过程中可能会延迟。

您可以切换到或可能吗?是的,futures看起来最有希望,因为它看起来很轻,并且示例有2个代码点(begin request和finish request)。我不想向项目添加更多依赖项,除非我必须这样做。也希望futures能与Python2.7 backport一起工作。意识到这些并不能解决问题。在释放锁之前,我必须确保邮件头已经发送。。。到目前为止,我已经设置了500毫秒的人工延迟-(.我唯一想到的建议是:使用请求来准备请求数据,但使用普通套接字来实际发送数据/接收响应。我认为您也可以使用请求来解析响应,但是,您会丢失自动处理的会话和重定向。您能对服务进行设计更改吗er端?不需要会话或重定向,所以我可能会深入到请求对象中,看看是否能找到有用的东西。Monkey patch socket或其他东西。我认为摘录不适用。我在单个线程中使用请求,因此它们会异步运行。我实际上是在寻找可以挂接的on_progress_下载事件进入(如下载进度条功能)。到目前为止,似乎是功能请求。如果您想知道何时收到响应的开始,@beiller,请查看摘录中提到的流媒体功能。这意味着您仍需等待响应开始,然后才能释放锁。如果会话池可以工作,我想这可能是最好的选择ion.Hi Don,感谢您的回答。但是,由于各种原因,您的要点都不起作用。会话池将不起作用,因为所有会话的nonce值都必须增加。无法更改服务器。批处理与我的锁定方法类似。nonce生成器是可重入的,因此无法工作。重试可能会起作用,但我得到了禁用的临时值f太多不好的瞬间。再次感谢你的回答,基本上请求不会支持我想说的。我承认它有点专业化。所以从技术上说你是对的!