Gevent ZeroMQ
ZeroMQ 被其作者描述为“充当并发框架的套接字库”。 它是一个非常强大的消息传递层,用于构建并发和分布式应用程序。
ZeroMQ 提供了多种套接字原语,其中最简单的是请求-响应套接字对。 套接字有两种感兴趣的方法 send 和 recv,这两种方法通常都是阻塞操作。 但这已由 Travis Cline 的一个出色的库(现在是 pyzmq 的一部分)进行了补救,该库使用 gevent.socket 以非阻塞方式轮询 ZeroMQ 套接字。
# Note: Remember to ``pip install pyzmq``
import gevent
import zmq.green as zmq
# Global Context
context = zmq.Context()
def server():
server_socket = context.socket(zmq.REQ)
server_socket.bind("tcp://127.0.0.1:5000")
for request in range(1,10):
server_socket.send("Hello")
print('Switched to Server for %s' % request)
# Implicit context switch occurs here
server_socket.recv()
def client():
client_socket = context.socket(zmq.REP)
client_socket.connect("tcp://127.0.0.1:5000")
for request in range(1,10):
client_socket.recv()
print('Switched to Client for %s' % request)
# Implicit context switch occurs here
client_socket.send("World")
publisher = gevent.spawn(server)
client = gevent.spawn(client)
gevent.joinall([publisher, client])
Switched to Server for 1
Switched to Client for 1
Switched to Server for 2
Switched to Client for 2
Switched to Server for 3
Switched to Client for 3
Switched to Server for 4
Switched to Client for 4
Switched to Server for 5
Switched to Client for 5
Switched to Server for 6
Switched to Client for 6
Switched to Server for 7
Switched to Client for 7
Switched to Server for 8
Switched to Client for 8
Switched to Server for 9
Switched to Client for 9
Simple Servers
# On Unix: Access with ``$ nc 127.0.0.1 5000``
# On Window: Access with ``$ telnet 127.0.0.1 5000``
from gevent.server import StreamServer
def handle(socket, address):
socket.send("Hello from a telnet!\n")
for i in range(5):
socket.send(str(i) + '\n')
socket.close()
server = StreamServer(('127.0.0.1', 5000), handle)
server.serve_forever()
WSGI Servers
Gevent 提供了两个 WSGI 服务器,用于通过 HTTP 提供内容。 此后称为 wsgi 和 pywsgi:
gevent.wsgi.WSGIServer
gevent.pywsgi.WSGIServer
在 1.0.x 之前的早期 gevent 版本中,gevent 使用 libevent 而不是 libev。 Libevent 包含一个快速的 HTTP 服务器,它被 gevent 的 wsgi 服务器使用。
在 gevent 1.0.x 中没有包含 http 服务器。 相反,gevent.wsgi 现在是 gevent.pywsgi 中纯 Python 服务器的别名。
Streaming Servers
如果您使用的是 gevent 1.0.x,则本节不适用
对于那些熟悉流式 HTTP 服务的人来说,核心思想是在标头中我们不指定内容的长度。 相反,我们保持连接打开并沿管道冲洗块,在每个前面加上一个表示块长度的十六进制数字。 当发送大小为零的块时,流将关闭。
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
8
<p>Hello
9
World</p>
0
无法在 wsgi 中创建上述 HTTP 连接,因为不支持流式传输。 相反,它必须缓冲。
from gevent.wsgi import WSGIServer
def application(environ, start_response):
status = '200 OK'
body = '<p>Hello World</p>'
headers = [
('Content-Type', 'text/html')
]
start_response(status, headers)
return [body]
WSGIServer(('', 8000), application).serve_forever()
然而,使用 pywsgi 我们可以将我们的处理程序编写为生成器并通过 chun 生成结果块
from gevent.pywsgi import WSGIServer
def application(environ, start_response):
status = '200 OK'
headers = [
('Content-Type', 'text/html')
]
start_response(status, headers)
yield "<p>Hello"
yield "World</p>"
WSGIServer(('', 8000), application).serve_forever()
但无论如何,与其他 Python 服务器相比,Gevent 服务器的性能是惊人的。 libev 是一项经过严格审查的技术,众所周知,它的衍生服务器在规模上表现良好。
要进行基准测试,请尝试使用 Apache Benchmark ab 或查看 Python WSGI 服务器的基准以与其他服务器进行比较。
$ ab -n 10000 -c 100 http://127.0.0.1:8000/