我使用bottle和gevent.wsgi实现了一个小型异步服务器。有一个例程用于实现长轮询,看起来很像bottle documentation中的“事件回调”示例:
def worker(body):
msg = msgbus.recv()
body.put(msg)
body.put(StopIteration)
@route('/poll')
def poll():
body = gevent.queue.Queue()
worker = gevent.spawn(worker, body)
return body
此处,msgbus
是ZMQ sub
套接字。
这一切都运行正常,但是如果客户端断开连接的话
worker
上已阻止msgbus.recv()
,绿色任务将挂起
围绕“永远”(好吧,直到收到消息),并且只会
找到有关断开连接的客户端尝试发送时的信息
响应。
如果我不想阻止,我可以使用msgbus.poll(timeout=something)
永远等待ipc消息,但我仍然无法检测到客户端
断开。
我想要做的事情就是获得类似客户端的引用
套接字,以便我可以在某种select
或poll
循环中使用它,
或者在我的greenlet中获得某种异步通知,但是
我不确定如何使用这些完成这些任务
框架(瓶子和gevent)。
有没有办法通知客户断开连接?
答案 0 :(得分:1)
啊哈! wsgi.input
变量(至少在gevent.wsgi
下)具有rfile
成员,该成员是类似文件的对象。 WSGI spec似乎不需要这样做,因此它可能不适用于其他服务器。
通过这个,我能够修改我的代码,看起来像:
def worker(body, rfile):
poll = zmq.Poller()
poll.register(msgbus)
poll.register(rfile, zmq.POLLIN)
while True:
events = dict(poll.poll())
if rfile.fileno() in events:
# client disconnect!
break
if msgbus in events:
msg = msgbus.recv()
body.put(msg)
break
body.put(StopIteration)
@route('/poll')
def poll():
rfile = bottle.request.environ['wsgi.input'].rfile
body = gevent.queue.Queue()
worker = gevent.spawn(worker, body, rfile)
return body
这很有效......
...除OpenShift外,您必须使用。{ 端口8000上的alternate frontend,支持websockets。