我試圖了解每個 Web 請求在 Rails 應用程式中的作業方式。為了理解我的邏輯,我撰寫了這個虛擬控制器。
class TestsController < ApplicationController
def index
puts 'Going to Sleep'
sleep 30.seconds
render json: { message: 'ok' }
end
end
我使用 puma 作為我的應用程式服務器。我在生產模式下運行 Rails 服務器,并 locahost:3000/tests在瀏覽器的 5 個不同選項卡中訪問。我的理解是因為 puma 是并發服務器,每個請求將在不同的執行緒下運行,這就是為什么第一個請求阻塞的請求不會阻塞第二個請求的請求,因為該請求將由單獨的執行緒處理。
但是當我在終端中查看服務器登錄時,我看到訊息Going to Sleep出現在第一個請求上,然后 ruby?? 進入睡眠狀態 30 秒。對于第二個請求和其他請求,我Going to Sleep在 30 秒內沒有在日志檔案中看到訊息(直到第一個請求完成睡眠)。這讓我很困惑,我認為對于瀏覽器上不同選項卡上的每 5 個請求,我會Going to Sleep立即看到訊息,并且沒有請求會相互阻止。但看起來我錯了。
有人可以向我解釋一下它是如何作業的嗎?我的第一個請求是阻止其他請求。這不是問題嗎?在現實世界的應用程式中,如果我對第 3 方應用程式進行 api 呼叫,并且獲得回應所需的時間比它會阻止其他用戶的請求嗎?或者我是否需要從不同的 IP 地址發出 http 請求才能使并發作業?請解釋。
UPDATA
下面是我的 puma 配置
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
uj5u.com熱心網友回復:
這個問題的答案是 Rails 沒有阻塞,但您的瀏覽器是。
瀏覽器經常重用現有的套接字連接以減少網路流量。在這種情況下,打開一個新選項卡到完全相同的 URL 將嘗試重用與服務器的現有套接字連接。
瀏覽器本質上是試圖通過已經打開的連接將請求傳送到服務器。由于此套接字連接正忙于等待控制器的index操作Tests,因此瀏覽器將阻塞。
要查看 Rails 確實會同時從同一個控制器執行相同的操作,您必須從另一個瀏覽器打開新請求,或者您也可以使用以下工具從命令列測驗它wget:
> wget -O - http://locahost:3000/tests &
> wget -O - http://locahost:3000/tests &
您會看到這兩個請求都會順利通過,因為它們每個都與服務器建立了新的唯一連接。
結論:
導軌作業正常。并發和執行緒按預期作業。只是您的瀏覽器被阻止,因為它試圖重用已經打開的套接字。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/510051.html
