Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 带有阻塞请求的Gevent异步服务器_Python_Sockets_Asynchronous_Gevent - Fatal编程技术网

Python 带有阻塞请求的Gevent异步服务器

Python 带有阻塞请求的Gevent异步服务器,python,sockets,asynchronous,gevent,Python,Sockets,Asynchronous,Gevent,我认为Gevent有一个非常常见的用例。我需要一个UDP服务器来侦听请求,并根据请求向外部web服务提交帖子。外部web服务实际上一次只允许一个请求 我希望有一个异步UDP服务器,以便可以立即检索和存储数据,这样我就不会错过任何请求(这一部分很容易使用DatagramServer gevent提供)。然后,我需要某种方法来串行地向外部web服务发送请求,但这样做不会破坏UDP服务器的异步 我首先尝试了monkey修补所有东西,最终得到的是一个快速的解决方案,但在这个解决方案中,我对外部web服务

我认为Gevent有一个非常常见的用例。我需要一个UDP服务器来侦听请求,并根据请求向外部web服务提交帖子。外部web服务实际上一次只允许一个请求

我希望有一个异步UDP服务器,以便可以立即检索和存储数据,这样我就不会错过任何请求(这一部分很容易使用DatagramServer gevent提供)。然后,我需要某种方法来串行地向外部web服务发送请求,但这样做不会破坏UDP服务器的异步

我首先尝试了monkey修补所有东西,最终得到的是一个快速的解决方案,但在这个解决方案中,我对外部web服务的请求没有任何速率限制,并且导致了错误

看起来我需要的是一个单一的非阻塞工作线程,在UDP服务器向非阻塞工作线程所在的队列添加任务时,将请求串行发送到外部web服务

我需要的是关于为其他任务(特别是队列)运行带有附加greenlet的gevent服务器的信息。我一直在使用DatagramServer的
serve_forever
功能,我认为我需要使用
start
方法,但没有找到多少关于如何将其组合在一起的信息

谢谢

编辑

答案很有效。我用@mguijarr的答案改编了代码,为我的用例生成了一个工作示例:

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()

我会这样做:

  • 编写一个以“队列”对象为参数的函数;此函数将连续处理队列中的项目。每个项目都应该是对web服务的请求。 此函数可以是模块级函数,而不是DatagramServer实例的一部分:

    def process_requests(q):
        while True:
            request = q.get()
            # do your magic with 'request'
            ...
    
  • 在DatagramServer中,使函数在greenlet中运行(如后台任务):

  • 当您在DatagramServer实例中收到UDP请求时,将请求推送到队列中

    self.__q.put(request)    
    

  • 这应该是你想要的。您仍然可以在DatagramServer上调用“永远服务”,没问题。

    谢谢您的回答。我会试着回去报告的。代码运行得很好。我已经用UDP服务器示例和您的解决方案中的工作示例代码更新了我的问题。谢谢
    self.__q.put(request)