为什么 gevent-websocket 是同步的? [英] why is gevent-websocket synchronous?

查看:27
本文介绍了为什么 gevent-websocket 是同步的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩 gevent 和 websockets.这是一个简单的回显服务器:

I am playing with gevent and websockets. This is a simple echo server:

from gevent.pywsgi import WSGIServer
from geventwebsocket.handler import WebSocketHandler
from gevent import sleep
from datetime import datetime
def app(environ, start_response):
    ws = environ['wsgi.websocket']
    while True:
        data = ws.receive()
        print('{} got data "{}"'.format(
            datetime.now().strftime('%H:%M:%S'), data))
        sleep(5)
        ws.send(data)

server = WSGIServer(("", 10004), app,
    handler_class=WebSocketHandler)
server.serve_forever()

和客户:

<html>
    <body>
        <button type="button" id="push_data">Push</button>
    </body>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.js"></script>
    <script>
        var ws = new WebSocket("ws://localhost:10004");
        ws.onmessage = function(evt) {
            console.log(evt)
        };
        $('#push_data').click(function(){
            console.log('sending data...');
            ws.send('sample data');
        });
    </script>
</html>

因为 gevent 我期待有几个 greenlet 异步提供数据;也就是说,如果我多次向 websocket 推送一些数据(快速点击 Push 按钮),我希望在等待 5 秒后将所有数据同时返回.

Because of gevent I was expecting to have several greenlets serving the data asynchronously; that is, if I pushed some data to the websocket several times (quickly clicking on the Push button), I was expecting to have it all back simultaneously after 5 seconds of waiting.

然而,无论我点击 Push 按钮的速度有多快,这都是我在控制台中得到的:

However, no matter how fast I click the Push button, this is what I get in the console:

18:28:07 got data "sample data"
18:28:12 got data "sample data"
18:28:17 got data "sample data"
18:28:22 got data "sample data"
18:28:27 got data "sample data"

为什么它会同步接收我的数据,每 5 秒暂停一次?如何将其变成异步服务器?

why does it receive my data synchronously, pausing every 5 seconds? How do I turn it into an asynchronous server?

推荐答案

行为是同步的,因为您自己的代码是同步的.gevent 只是一个使用事件循环的协程库.它不会神奇地将同步代码变成异步代码.

The behavior is synchronous because your own code is synchronous. gevent is only a coroutine library using an event loop. It does not magically turn synchronous code into asynchronous code.

请查看以下文档:http://www.gevent.org/servers.html

据说服务器每个连接(不是每个请求)生成一个greenlet.因此,对同一连接的多个请求的执行是串行化的.

It is said that the servers spawn one greenlet per connection (not per request). The execution of multiple requests for the same connection is therefore serialized.

如果你想同时处理同一个连接的多个请求,你需要产生新的greenlets,或者将处理委托给一个greenlets池.

If you want to concurrently handle multiple requests for the same connection, you need to spawn new greenlets, or delegate the processing to a pool of greenlets.

这是一个示例(在每个请求时生成一个 greenlet):

Here is an example (spawning a greenlet at each request):

import gevent
from gevent.pywsgi import WSGIServer
from gevent.lock import Semaphore
from geventwebsocket.handler import WebSocketHandler
from datetime import datetime

def process(ws,data,sem):
    print('{} got data "{}"'.format(datetime.now().strftime('%H:%M:%S'), data))
    gevent.sleep(5)
    with sem:
        ws.send(data)

def app(environ, start_response):
    ws = environ['wsgi.websocket']
    sem = Semaphore()
    while True:
        data = ws.receive()
        gevent.spawn(process,ws,data,sem)

server = WSGIServer(("", 10004), app,handler_class=WebSocketHandler)
server.serve_forever()

注意信号量的存在.由于处理是并发的,需要防止两个并发的greenlet同时在socket上写,导致消息损坏.

Note the presence of the semaphore. Because the processing is concurrent, it is needed to prevent two concurrent greenlets to write at the same time on the socket, resulting in corrupted messages.

最后一点,对于这个实现,不能保证回复会按照请求的顺序发送.

Last point, with this implementation, there is no guarantee that the replies will be sent in the order of the requests.

这篇关于为什么 gevent-websocket 是同步的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆