Python - 使用带有多线程的nonce

bei*_*ler 9 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)的此实例在多个Thread之间共享.

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
Run Code Online (Sandbox Code Playgroud)

Don*_*kby 2

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

\n
\n

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

\n

如果您担心阻塞 IO 的使用,有很多项目将请求与 Python\xe2\x80\x99s 异步框架之一相结合。两个很好的例子是 grequests 和 requests-futures。

\n
\n

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

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

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

\n

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

\n