我编写了一个 HTTP 服务器,它生成由 JSON 结构事件组成的无尽 HTTP 流。类似于 Twitter 的流 API。这些事件由\n
(根据服务器发送的事件 http://en.wikipedia.org/wiki/Server-sent_events与内容类型:文本/事件流)并且长度可以变化。
响应是
- 由于无限流而分块(HTTP 1.1 Transfer-Encoding:分块)
- 压缩(内容编码:gzip)以节省带宽。
我希望在这些行到达后立即在 Python 中使用它们,并尽可能提高资源效率,而不需要重新发明轮子。
由于我目前正在使用 python-requests,你知道如何使其工作吗?
如果您认为 python-requests 在这里无济于事,我完全欢迎替代框架/库。
我当前的实现是基于requests http://requests.readthedocs.org/en/latest/和用途iter_lines(...)
接收线路。但是chunk_size
参数很棘手。如果设置为1
它非常占用 CPU 资源,因为某些事件可能有几千字节。如果设置为大于 1 的任何值,则某些事件会卡住,直到下一个事件到达并且整个缓冲区“被填满”。事件之间的时间可能是几秒钟。
我预计chunk_size
是某种“要接收的最大字节数”,如 unix 中的recv(...)
。相应的手册页显示:
接收调用通常会返回任何可用数据,最多可达
请求金额,而不是等待收到全额金额
要求。
但这显然不是请求库中的工作方式。他们或多或少将其用作“要接收的确切字节数”。
在查看他们的源代码时,我无法确定哪个部分负责。也许是 httplib 的 Response 或 ssl 的 SSLSocket。
作为解决方法,我尝试将服务器上的行填充到块大小的倍数。
但是请求库中的块大小用于从压缩的响应流。
所以这不会起作用,直到我可以填充我的线条,以便他们压缩的字节序列是块大小的倍数。但这似乎太老套了。
我读过 Twisted 可用于客户端上 http 流的非阻塞、非缓冲处理,但我只找到了在服务器上创建流响应的代码。
它不是requests
' 错的是你的iter_lines()
呼叫被阻塞。
The Response.iter_lines() https://github.com/kennethreitz/requests/blob/0caa2432123bab2d991e635ce558226d019d7bc7/requests/models.py#L652方法调用Response.iter_content() https://github.com/kennethreitz/requests/blob/0caa2432123bab2d991e635ce558226d019d7bc7/requests/models.py#L614,这称为urllib3
's HTTPResponse.stream() https://github.com/kennethreitz/requests/blob/3ef41153498917bc4d01123b2f7a8fbd8e7bcf63/requests/packages/urllib3/response.py#L219,这称为HTTPResponse.read() https://github.com/kennethreitz/requests/blob/3ef41153498917bc4d01123b2f7a8fbd8e7bcf63/requests/packages/urllib3/response.py#L141.
这些调用传递一个块大小,这是传递到套接字的内容self._fp.read(amt)
。这是有问题的调用,因为self._fp
是一个文件对象,由socket.makefile() http://docs.python.org/2/library/socket.html#socket.socket.makefile(正如所做的那样httplib module http://docs.python.org/2/library/httplib.html);和这个.read()
call will阻塞直到amt
读取(压缩)字节。
这个低级套接字文件对象确实支持.readline()
调用会更有效地工作,但是urllib3
处理压缩数据时不能使用此调用;行终止符在压缩流中将不可见。
很遗憾,urllib3
不会打电话self._fp.readline()
当响应也没有被压缩时;调用的结构方式很难传递您想要以行缓冲模式而不是块缓冲模式读取的内容。
我必须说 HTTP 并不是用于流事件的最佳协议;我会为此使用不同的协议。我首先想到的是 Websocket,或者是适合您的特定用例的自定义协议。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)