异步调用之前发送的 HTTP 响应 returns
HTTP Response sent before async call returns
我还不了解 Web 服务器线程的行为,如果我进行异步调用说,一个数据库,并立即 return 响应(说 OK )给客户端,甚至不等待异步回拨给 return。首先,这是一个好方法吗?进行异步调用的线程会发生什么情况,如果它再次用于服务另一个请求,然后是先前对该特定线程的异步调用 returns。或者 web 服务器是否持有此线程,等待它进行的异步调用,returns。那么问题将是许多挂起的线程将打开,因为 Web 服务器将可用于接受更多请求。我正在寻找答案。
这取决于此异步操作是否执行了应通知客户端的事情。
如果您 return 200 OK(即成功完成)并且稍后异步操作失败,那么客户端将不知道该错误。
您当然有一些选择,例如通过 websocket 发送某种推送通知或发送另一个请求 return 实际结果等等。所以基本上取决于你的需求...
这取决于您的 HTTP 服务器的工作方式。但是你应该非常小心。
假设您有一个主事件循环来处理传入的 HTTP 连接,以及管理 HTTP 通信的工作线程。
只有当工作线程有效地完全准备好时,才应将其视为准备好接受新的 HTTP 请求管理。
就纯 HTTP 而言,更重要的是 避免在收到整个查询之前发送响应。这看起来很简单,通常也是如此。但是如果查询作为一个主体,它可能是一个分块的主体,那么接收整个消息可能需要一些时间。
您之前应该永远不要 发送响应,除非它是类似于 400 错误请求响应,然后是真正的 tcp/ip 连接关闭。如果你没有这样做,并且你有一个消息长度解析问题,你在查询结束之前发送响应的事实可能会导致安全问题。在某种 http 走私问题中,它可用于利用您的服务器与服务器前面的任何其他 HTTP 代理(ssl 终结器、反向代理等)之间的消息解析差异。对于这个代理,如果你做出了回应,就意味着你得到了完整的消息,它可以发送下一条消息,实际上你会认为这只是正文的另一部分。
现在,如果您有完整的消息,您可以决定发送早期响应并分离异步任务以真正执行某些操作。但这意味着:
- 你必须假设不应再生成输出,你不会尝试向请求发出者发送任何输出,你应该考虑到通信现已关闭
- 工作线程不应接收新的管理请求,这是困难的部分。如果这个线程被标记为可用于新请求,它也可能被线程管理器 killed (你在 Nginx 或 Apache 请求计数器中与工作人员相关联,并且他们在到达后被杀死一个限制,创造新的)。它也可能会收到一个优雅的重新加载命令(通常是一个杀戮)等
所以你开始进入一个区域,你应该了解 HTTP 服务器的内部结构,它可能由你管理,也可能不由你管理,并且迟早会出现更改。然后你开始制作非常奇怪的东西,这通常会导致 奇怪的问题,难以重现。
通常处理 异步任务 的最佳方法是使用 消息系统 ,同时仍然能够理解发生了什么。将任务列表放入 queue,并获得一个 并行异步工作进程 来处理这些任务。如果需要,跟踪这些任务的状态。
同样的事情可能适用于客户端,在收到非常快速的 HTTP 响应后,它可能需要对任务状态执行一些 ajax 状态轮询。您可能只需检查队列中任务的状态即可发送响应。
您将对整个事情有更多的控制权。
对我来说,我真的不喜欢分离线程,来自奇怪的代码,在没有任何输出状态或报告错误的情况下执行繁重的任务,并且可能阻止良好的应用程序停止调用(仍在等待奇怪的线程加入)这并不意味着 killall。
我还不了解 Web 服务器线程的行为,如果我进行异步调用说,一个数据库,并立即 return 响应(说 OK )给客户端,甚至不等待异步回拨给 return。首先,这是一个好方法吗?进行异步调用的线程会发生什么情况,如果它再次用于服务另一个请求,然后是先前对该特定线程的异步调用 returns。或者 web 服务器是否持有此线程,等待它进行的异步调用,returns。那么问题将是许多挂起的线程将打开,因为 Web 服务器将可用于接受更多请求。我正在寻找答案。
这取决于此异步操作是否执行了应通知客户端的事情。
如果您 return 200 OK(即成功完成)并且稍后异步操作失败,那么客户端将不知道该错误。
您当然有一些选择,例如通过 websocket 发送某种推送通知或发送另一个请求 return 实际结果等等。所以基本上取决于你的需求...
这取决于您的 HTTP 服务器的工作方式。但是你应该非常小心。
假设您有一个主事件循环来处理传入的 HTTP 连接,以及管理 HTTP 通信的工作线程。 只有当工作线程有效地完全准备好时,才应将其视为准备好接受新的 HTTP 请求管理。
就纯 HTTP 而言,更重要的是 避免在收到整个查询之前发送响应。这看起来很简单,通常也是如此。但是如果查询作为一个主体,它可能是一个分块的主体,那么接收整个消息可能需要一些时间。 您之前应该永远不要 发送响应,除非它是类似于 400 错误请求响应,然后是真正的 tcp/ip 连接关闭。如果你没有这样做,并且你有一个消息长度解析问题,你在查询结束之前发送响应的事实可能会导致安全问题。在某种 http 走私问题中,它可用于利用您的服务器与服务器前面的任何其他 HTTP 代理(ssl 终结器、反向代理等)之间的消息解析差异。对于这个代理,如果你做出了回应,就意味着你得到了完整的消息,它可以发送下一条消息,实际上你会认为这只是正文的另一部分。
现在,如果您有完整的消息,您可以决定发送早期响应并分离异步任务以真正执行某些操作。但这意味着:
- 你必须假设不应再生成输出,你不会尝试向请求发出者发送任何输出,你应该考虑到通信现已关闭
- 工作线程不应接收新的管理请求,这是困难的部分。如果这个线程被标记为可用于新请求,它也可能被线程管理器 killed (你在 Nginx 或 Apache 请求计数器中与工作人员相关联,并且他们在到达后被杀死一个限制,创造新的)。它也可能会收到一个优雅的重新加载命令(通常是一个杀戮)等
所以你开始进入一个区域,你应该了解 HTTP 服务器的内部结构,它可能由你管理,也可能不由你管理,并且迟早会出现更改。然后你开始制作非常奇怪的东西,这通常会导致 奇怪的问题,难以重现。
通常处理 异步任务 的最佳方法是使用 消息系统 ,同时仍然能够理解发生了什么。将任务列表放入 queue,并获得一个 并行异步工作进程 来处理这些任务。如果需要,跟踪这些任务的状态。 同样的事情可能适用于客户端,在收到非常快速的 HTTP 响应后,它可能需要对任务状态执行一些 ajax 状态轮询。您可能只需检查队列中任务的状态即可发送响应。
您将对整个事情有更多的控制权。
对我来说,我真的不喜欢分离线程,来自奇怪的代码,在没有任何输出状态或报告错误的情况下执行繁重的任务,并且可能阻止良好的应用程序停止调用(仍在等待奇怪的线程加入)这并不意味着 killall。