Sunday, July 8, 2018

queue, channel, asynchronous API

以前讀 Rich Hickey 的 Simple Made Easy 時,有一回他講了 If you're not using queues extensively, you should be. You should start right away, like right after this talk. (如果你沒有常常使用 queue 的話,你應該要多用一些。你應該立刻開始…聽完現在的 talk 就開始吧。)

紅色那段英文的上下文, Rich Hickey 的論點是: Queue 可以讓 when 和 where 這兩件事被分開來。這個說法太抽象了,我一直無法理解它。此外,看完那段話之後,也還是想不出來,我寫程式的時候,哪些地方有可能用 queue 去改善?

而公司的同事最近在設計架構時,用了 aws  的 SQS 服務。我隨口問了他,為什麼要用使用 queue ?他回答: producer 和 consumer 的速度根據估計會有很明顯的差距,所以使用 queue 來做解耦,就可以大幅改善效率。

同事的理由,讓我忍不住回頭去看了一下 Rich Hickey 曾經寫過的關於 channel 的設計理由:
There comes a time in all good programs when components or subsystems must stop communicating directly with one another. This is often achieved via the introduction of queues between the producers of data and the consumers/processors of that data. This architectural indirection ensures that important decisions can be made with some degree of independence, and leads to systems that are easier to understand, manage, monitor and change, and make better use of computational resources, etc.

嗯,這一句理由總算是把問題講得清楚了一些,至少也提到了計算資源的消耗問題

那還有什麼情況也是適合用 queue 來處理問題呢? 為什麼 Rich Hickey 說,要多用一些?那如果卯起來用 queue 的話,還可以用到什麼程度?

我在 Martin Trojer 的文章裡,終於也找到了部分的答案: 像 Nodejs ,只要一遇到 I/O 就是用 callback/promise 來處理,以避免 I/O wait 。實際上, callback/promise 也可以用 queue 去取代。(Martin Trojer 的原文內容要旨為:如果要使用 clojure 的 core.async library 的話,正確的使用方式,必須搭配 asynchronous I/O API )

另外,如果不是只考慮計算資源消耗,而是考慮系統的單純性 (simple system) 的話,也有人用 event driven programming 來描述這個概念:

He's really just giving a fuzzy description for the concept of job pools and event driven programming. So you pack a function call into a generic Job object, push that into a queue, and have one or more worker threads work on that queue. The Job then dispatches more Jobs into the queue upon completion.