我认为Gevent是一个非常常见的用例。我需要一个侦听请求的UDP服务器,并根据请求向外部Web服务提交POST。外部Web服务基本上一次只允许一个请求。
我希望有一个异步UDP服务器,以便可以立即检索和存储数据,这样我就不会错过任何请求(这部分很容易通过DatagramServer gevent提供)。然后我需要一些方法来串行地向外部Web服务发送请求,但这样做不会破坏UDP服务器的异步。
我首先尝试使用猴子修补所有内容,而我最终得到的是一个快速解决方案,但我对外部Web服务的请求不受任何速率限制,导致错误。
似乎我需要的是一个非阻塞工作者,以便在UDP服务器将任务添加到非阻塞工作者正在工作的队列中时,以串行方式向外部Web服务发送请求。
我需要的是有关运行gevent服务器以及其他任务(特别是队列)的其他greenlet的信息。我一直在使用DatagramServer的serve_forever
功能,并认为我需要使用start
方法,但是我们还没有找到有关它如何使用的信息合在一起。
谢谢,
修改
答案非常有效。我已经使用@mguijarr的答案调整了UDP server example代码,为我的用例提供了一个工作示例:
from __future__ import print_function
from gevent.server import DatagramServer
import gevent.queue
import gevent.monkey
import urllib
gevent.monkey.patch_all()
n = 0
def process_request(q):
while True:
request = q.get()
print(request)
print(urllib.urlopen('https://test.com').read())
class EchoServer(DatagramServer):
__q = gevent.queue.Queue()
__request_processing_greenlet = gevent.spawn(process_request, __q)
def handle(self, data, address):
print('%s: got %r' % (address[0], data))
global n
n += 1
print(n)
self.__q.put(n)
self.socket.sendto('Received %s bytes' % len(data), address)
if __name__ == '__main__':
print('Receiving datagrams on :9000')
EchoServer(':9000').serve_forever()
答案 0 :(得分:1)
我将如何做到这一点:
编写一个带有"队列的函数"对象作为参数;此函数将持续处理队列中的项目。每个项目都应该是对Web服务的请求。 此函数可以是模块级函数,而不是DatagramServer实例的一部分:
def process_requests(q):
while True:
request = q.get()
# do your magic with 'request'
...
使函数在greenlet中运行(如后台任务):
self.__q = gevent.queue.Queue()
self.__request_processing_greenlet = gevent.spawn(process_requests, self.__q)
在DatagramServer实例中收到UDP请求时,将请求推送到队列
self.__q.put(request)
这应该做你想要的。你仍然打电话给'serve_forever'在DatagramServer上,没问题。