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

查看:306
本文介绍了为什么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(快速单击推送"按钮),那么我期望在等待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.

但是,无论我单击按钮"有多快,这都是我在控制台中看到的:

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

Please have a look at the documentation at: http://www.gevent.org/servers.html

据说服务器每个连接(不是每个请求)产生一个绿色组件.因此,对同一连接的多个请求的执行将被序列化.

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.

如果要同时处理同一连接的多个请求,则需要生成新的greenlet,或将处理委托给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同时在套接字上写入,从而导致消息损坏.

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天全站免登陆