我需要创建一个python中间件,它将执行以下操作:
a)接受来自多个客户的http get / post请求。
b)修改并将这些请求发送到后端远程应用程序(通过套接字通信)。我对这个远程应用程序没有任何控制权。
c)从后端应用程序接收处理结果,并将这些结果返回给请求客户端。
现在客户端期待同步请求/响应方案。但后端应用程序不会同步返回结果。也就是说,某些请求的处理时间比其他请求要长得多。因此,
客户端1:发送http请求C1 - >得到回应R1
客户端2:发送http请求C2 - >得到回应R2
客户端3:发送http请求C3 - >得到回应R3
Python中间件以某种顺序接收它们:C2,C3,C1。按顺序将它们分派给后端(作为非http消息)。后端以混合顺序R1,R3,R2响应结果。 Python中间件应将这些响应打包回http响应对象,并将响应发送回相关客户端。
是否有任何示例代码可以对此类行为进行编程。似乎有类似于20个不同的web框架的python,我很困惑哪一个最适合这种情况(更喜欢尽可能轻量级的东西......我会认为Django太重了......我试过瓶子,但我不知道如何为这种情况编程。)
=============================================== =
更新(基于以下讨论):请求具有请求ID。响应具有响应ID(应该与它们对应的请求ID匹配)。中间件和远程后端应用程序之间只有一个套接字连接。虽然我们可以维护{request_id:ip_address}字典,但问题是如何构造到正确客户端的HTTP响应对象。我假设,线程可以解决这个问题,每个线程都维护自己的响应对象。
答案 0 :(得分:3)
螺丝框架。这正是asyncore的任务。该模块允许基于事件的网络编程:给定一组套接字,当数据准备就绪时,它会回调给定的处理程序。这样,线程不一定只是为了勉强等待一个套接字上的数据到达并痛苦地将其传递给另一个线程。您必须自己实现http处理,但可以在其上找到示例。或者,您可以使用uwsgi的异步功能,这将允许您的应用程序与现有的Web服务器集成,但默认情况下不会与asyncore集成 - 尽管它不难实现工作。取决于具体需求。
答案 1 :(得分:2)
引用您的评论:
中间件使用到后端的单个持久套接字连接。来自中间件的所有请求都通过此单个套接字转发。客户端会发送请求ID及其请求。响应ID应与请求ID匹配。所以问题仍然存在:中间件(Web服务器)如何跟踪哪个请求ID属于哪个客户端?我的意思是,有没有办法让中间件中的cgi脚本创建一个元组的数据库,一旦响应ID匹配,然后发送一个http响应clientip:clienttcpport?
在中间件中进行所有这些处理有什么特殊原因吗?如果更合适,你应该可以在装饰器或其他地方完成所有这些工作。
无论如何,您需要维护一个全局并发字典(扩展dict
并使用threading.Lock
保护它)。根据新请求,将给定的request-id存储为密钥,并将其关联到相应的客户端(发送方)。每当你的后端响应时,从这个字典中检索客户端,并删除该条目,使其不会永远累积。
更新:某人已经为您扩展了字典 - 请检查this answer。
答案 2 :(得分:0)
最终,您将从客户端的同步http请求-响应协议转变为带有后端的异步排队/消息协议。因此,您有两种选择(1)要么让请求等到后端没有任何未完成的工作,然后进行处理(2)编写一些将后端响应与其关联的请求结合起来的东西(使用请求字典或类似的东西)
一种方法可能是在一个线程中运行服务器,而在另一个线程中处理后端(请参阅... Run Python HTTPServer in Background and Continue Script Execution),或者可能要看aiohttp(https://docs.aiohttp.org/en/v0.12.0/web.html)