如何在长时间排队后忽略请求 tomcat
How to ignore request after long queue time tomcat
当后端tomcat服务器收到请求时,如果没有可用的工作线程,则请求排队。我有一个前端在显示超时并终止连接之前等待(比如说)30 秒。如果请求在队列中时前端超时,即使连接终止,当请求到达队列顶部并且工作线程可用时,请求仍由服务器处理。但是这个处理是多余的,因为前端已经超时了。
此外,请求会一直留在队列中,直到它有机会被处理,实质上是阻塞队列以等待前端仍需要响应的新请求。
我愿意接受任何后端更改(Tomcat/JVM 或其他)
P.s。我知道 tomcat 没有关于接受队列的任何信息。我读到 comm stack
有那个信息。但是我仍然不清楚可以做什么
如果您不想在一段时间后等待,您首先需要取消 queue 请求。唯一的方法是将 TCP 积压设置为零,并希望 OS 合作。
你可能想 re-think 一些事情,在这里,你的应用程序。
首先,您可以调整 TCP 积压,但当然请求可能需要任意时间才能完成。因此,如果您只有 1 个请求处理线程并且它很忙,那么客户端将不得不不断地发出请求,直到它可以获得一个空闲线程(因为积压为零)。 in-flight 请求完成的时间是 un-knowable,因此您必须 re-try.
其次,客户端无法知道它的请求是否在 TCP 积压中等待,或者它是否正在被主动服务,因此它要么等待收到响应,要么 time-out。如果你不知道请求是否已经开始,你将不会真正知道是否值得等待。
第三,任何 TCP 连接都可能随时中断或失败。因此,如果服务器收到请求,即使客户端没有收到响应,它也可能会处理它。 (如果客户放弃,这基本上是相同的情况。)
有几种方法可以处理上述情况。
一种方法是使用称为 100-Continue 的 HTTP 功能,其中客户端通过发送 request-line 和 header 来发出请求,包括 Expect: 100-continue
header但没有请求 body 以及 POST 或 PUT 请求。在准备好处理请求之前,服务器不会使用 100 Continue
响应代码进行回复。如果你没有在你的例子中得到 100 Continue
30 秒 window,您关闭连接,然后...不要继续请求。如果您 do 得到 100 Continue
响应,您就可以发送您的请求 body,据推测,该请求将包含实际服务该请求所需的一切。如果服务器没有收到请求 body,它可能会(某种程度上)优雅地失败并且请求基本上被忽略。
服务端检测客户端是否还在的另一种方式是尝试向客户端写回数据。服务器中的缓冲 OS 和网络有时会使这变得不切实际,并且可能会降低您的网络性能(因为响应必须 chunked 才能做到这一点).如果客户端不存在并且您没有受到 OS 的阻碍,那么您将收到 IO 错误并且您的 server-side 进程可以中止。
您可能想要做的另一件事是确保所有(或大部分)进程都是 idempotent。基本上,允许对同一事物的重复请求不是问题(当然,性能除外)。您可以使用 transaction-tokens 之类的东西或其他一些“可过期”资源,这些资源允许客户端一遍又一遍地请求相同的东西,但它只会成功一次。而且,出于您的目的,您希望非常快速地检查此类令牌的有效性,以免造成性能问题。
要吞下的东西太多了,但希望其中的内容对您有所帮助。
当后端tomcat服务器收到请求时,如果没有可用的工作线程,则请求排队。我有一个前端在显示超时并终止连接之前等待(比如说)30 秒。如果请求在队列中时前端超时,即使连接终止,当请求到达队列顶部并且工作线程可用时,请求仍由服务器处理。但是这个处理是多余的,因为前端已经超时了。
此外,请求会一直留在队列中,直到它有机会被处理,实质上是阻塞队列以等待前端仍需要响应的新请求。
我愿意接受任何后端更改(Tomcat/JVM 或其他)
P.s。我知道 tomcat 没有关于接受队列的任何信息。我读到 comm stack
有那个信息。但是我仍然不清楚可以做什么
如果您不想在一段时间后等待,您首先需要取消 queue 请求。唯一的方法是将 TCP 积压设置为零,并希望 OS 合作。
你可能想 re-think 一些事情,在这里,你的应用程序。
首先,您可以调整 TCP 积压,但当然请求可能需要任意时间才能完成。因此,如果您只有 1 个请求处理线程并且它很忙,那么客户端将不得不不断地发出请求,直到它可以获得一个空闲线程(因为积压为零)。 in-flight 请求完成的时间是 un-knowable,因此您必须 re-try.
其次,客户端无法知道它的请求是否在 TCP 积压中等待,或者它是否正在被主动服务,因此它要么等待收到响应,要么 time-out。如果你不知道请求是否已经开始,你将不会真正知道是否值得等待。
第三,任何 TCP 连接都可能随时中断或失败。因此,如果服务器收到请求,即使客户端没有收到响应,它也可能会处理它。 (如果客户放弃,这基本上是相同的情况。)
有几种方法可以处理上述情况。
一种方法是使用称为 100-Continue 的 HTTP 功能,其中客户端通过发送 request-line 和 header 来发出请求,包括 Expect: 100-continue
header但没有请求 body 以及 POST 或 PUT 请求。在准备好处理请求之前,服务器不会使用 100 Continue
响应代码进行回复。如果你没有在你的例子中得到 100 Continue
30 秒 window,您关闭连接,然后...不要继续请求。如果您 do 得到 100 Continue
响应,您就可以发送您的请求 body,据推测,该请求将包含实际服务该请求所需的一切。如果服务器没有收到请求 body,它可能会(某种程度上)优雅地失败并且请求基本上被忽略。
服务端检测客户端是否还在的另一种方式是尝试向客户端写回数据。服务器中的缓冲 OS 和网络有时会使这变得不切实际,并且可能会降低您的网络性能(因为响应必须 chunked 才能做到这一点).如果客户端不存在并且您没有受到 OS 的阻碍,那么您将收到 IO 错误并且您的 server-side 进程可以中止。
您可能想要做的另一件事是确保所有(或大部分)进程都是 idempotent。基本上,允许对同一事物的重复请求不是问题(当然,性能除外)。您可以使用 transaction-tokens 之类的东西或其他一些“可过期”资源,这些资源允许客户端一遍又一遍地请求相同的东西,但它只会成功一次。而且,出于您的目的,您希望非常快速地检查此类令牌的有效性,以免造成性能问题。
要吞下的东西太多了,但希望其中的内容对您有所帮助。