我們在之前的章節列舉了Pipeline(管道)的各種優點,但有時候,盡管管道沒有準備好,我們的程序依然還是要幹活
的,這種處理方式,被稱為“Queue”(隊列)。
這意味著,一旦管道的某個階段完成了工作,將其存儲在內存中的臨時位置,以便其他階段可以稍後檢索 它,而你無需保持其引用。在“Channels”章節,我們討論了帶緩沖的通道,你可以把它視作隊列的一 種。
雖然在系統中引入隊列功能非常有用,但它通常是優化程序時希望採用的最後一種技術之一。過早地添加
隊列會隱藏同步問題,例如死鎖和活鎖,並且,隨著程序不斷重構,你可能會發現需要更多或更少的隊
列。
那麽使用隊列有什麽好處呢?隊列通常用來嘗試解決性能問題。隊列幾乎不會減少程序的總運行時間,它
只會讓程序的行為有所不同。
讓我們看個簡單的管道例子:
done := make(chan interface{})
defer close(done)
zeros := take(done, 3, repeat(done, 0))
short := sleep(done, 1*time.Second, zeros)
long := sleep(done, 4*time.Second, short)
pipeline := long
這個管道鏈共有4個階段:
你可以看到,這個管道耗時13秒。短耗時階段花費了大約9秒。
如果我們給管道加入緩存會怎麽樣?讓我們試試在長短耗時階段之間添加個緩沖:
done := make(chan interface{})
defer close(done)
zeros := take(done, 3, repeat(done, 0))
short := sleep(done, 1*time.Second, zeros)
buffer := buffer(done, 2, short) // Buffers sends from short by 2
long := sleep(done, 4*time.Second, short)
pipeline := long
整個管道依然是13秒,但短耗時階段時長降低到了3秒,看來加入緩存是有效的。
但是如果整個管道仍然需要13秒來執行,這對我們有什麽幫助?
我們來看看下面這個操作:
p := processRequest(done, acceptConnection(done, httpHandler))
這條管道會持續運行直到被取消,並且在取消之前會持續接受連接。
在這期間,你肯定不希望處理連接的 processRequest因acceptConnection接受連接而阻塞,你會希望processRequest是持續可用的,否則程序的用戶可能會發現連接請求被拒絕。
因此,隊列的價值並不是減少了某個階段的運行時間,而是減少了它處於阻塞狀態的時間。 這可以讓程序繼續工作。 在這個例子中,用戶可能會在他們的請求中感受到延遲,但不會被拒絕服務。
通過這種方式,隊列的真正用途是將操作流程分離,以便一個階段的運行時間不會影響另一個階段的運行
時間。
以這種方式解耦來改變整個系統的運行行為,這取決於你的程序,產生的結果可能是好的也可能
是不好的。