轉到電商後,經歷過第一次雙十一的洗禮,總算是親身體驗大流量的刺激與震撼了 :D,其中的辛苦我就不多說了,這次都還是仰賴經驗老到的同事們渡過難關的。不過這次我們能安然渡過,先前開發的排隊機制功不可沒。但是這次我們也發現到排隊機制其實還有些優化改善的空間,可以讓排隊中的消費者有更好的體驗。
圖片出處: https://tw.appledaily.com/new/realtime/20181124/1472338/
雙十一過後,我試著在思考如何改善排隊的做法… 不過很少看到有文章在探討這類機制該如何開發的細節? (大多是高流量高併發,淘寶雙十一超大規模架構之類的) 於是我試著研究這個議題,也簡單的寫了 POC 來驗證想法,就順手寫了這篇…。
這篇跟前一篇 微服務基礎建設: 斷路器 #1, 服務負載的控制 的出發點是一樣的,都是要透過某些程序,限制同時取用服務的請求,確保服務端有足夠的資源來完成任務。只是上一篇控制的是 server 能 “同時” 受理多少 request 的管控機制,控制的是處理交易的 “速度”。而這篇我要探討的是這些 request 應該要用什麼樣的規則與順序,決定那些 request 可以被服務? 換個角度說,排隊機制決定那些人 (request) 可以進入店面消費,而流量管控則決定櫃台一分鐘能服務多少人 (request)。
這兩件事情都做到位,你就能掌握好服務對使用者的 QoS (Quality Of Service) 了,可以兼顧服務的質跟量。質是指還未能被服務到的客戶是否仍能有良好的體驗,而量則是指交易處理的速度 (TPS, transaction per second)。這兩者都是線上交易很關鍵的一環,不過往往 developer 都不會把它擺在第一順位 (一般情況是: 規格就沒這項啊,通常都是上線了有人來抱怨再說…)
有時候,無知就是福啊… 沒想到我也默默忍受了這個地雷一年多了都沒發現。Container 透過 volume 掛載儲存空間到容器內部,會有一定的效能折損是一定的。然而 container 本身透過 AUFS 也有一定的效能折損啊。原本很天真的想: 我都在本機使用,想想應該不會差到哪裡去,直到膝蓋中了一箭…
事情要回顧到兩年前,我開始把 Blog 搬到 GitHub Pages 上面來開始說起… 當時為了避開 Ruby for Windows 地獄,我一直用 Docker for Windows 跑 Jekyll 在我自己 PC build website 測試,直到前一陣子突然想用 LCOW 來替代,才意外發現 volume 跟 container 內部的 I/O 效能有天跟地的差別…
不過,不論你對測試的數據有沒有興趣,請務必看一下 結論 這個章節。雖然 (先雷一下結果好了) 透過 LCOW 掛上 volume 的 I/O 效能不好看,但是別急著否定他。搞清楚它的定位,搞清楚什麼應用場景才是適合 LCOW 發揮的領域,善用他才是正途。
原本 “服務量控制” 這是我要拿來寫 “架構面試題 #3” 的內容的,不過想想拿這個來考白板也太殘忍了吧! 同時這些基礎知識恰好是微服務架構裡面 “斷路器” (circuit breaker) 很重要的基礎,因此這篇就順理成章地接在 “服務發現” (service discovery) 的下一個主題了。
這篇文章我還不打算介紹 “斷路器” 該怎麼使用,取而代之的是使用斷路器的基礎知識: 流量控制。這裡指的流量不光是網路封包而已,而是泛指某個服務在一定時間內能夠處理的服務量。”服務量” 指的可能是訂單件數,可能是出貨量,也可能是發送的訊息數等等。先要能搞清楚如何掌握服務量,你才能預測系統何時會到達極限,何時該啟動斷路器保護整個系統。
雖然微服務跟容器化是兩回事,不過兩者的搭配是絕佳組合啊,所以我決定先花點篇幅,先交代如何將 web api 容器化部署的問題 (self-host or IIS host)。部署這件事,過去都是 operation team 解決掉了,不需要 development team 傷腦筋。現在微服務需要更密切的整合,必須要同時能掌握 development 跟 operation 的 know how, 才能正確的拿捏該捨掉那些東西。這篇就是從這角度,告訴你 IIS 與 Self Host 兩種開發與部署的模式該如何取捨。我先說明一下採用 Self-Host 的考量,同時也會示範一下如何開發一個通用的 Self-Host class library, 微服務的應用上,你勢必會有很多大量的服務需要開發,先把這個通用的 Self-Host 架構搞定,接著統一處理其他微服務的各種 infrastructure (如下篇介紹的 consul) 的整合,可以替整個團隊省下不少功夫。
在上一篇 容器化的微服務開發 #1, IP查詢架構與開發範例 我拿 IP 地區查詢服務當作範例,用容器驅動開發的觀念,實作了微服務版本的 IP2C Service。我提到的 “Container Driven Development” 概念,就是假設你將來 “一定” 會用容器化的方式來部署的話,那麼在架構設計之初就能盡可能的對容器最佳化。這邊的最佳化,不是要你 多做 一些什麼,反而是要你多思考哪些是多餘的部分,直接拿掉改用容器 (container or orchestration) 來替代。適度的簡化,可以讓 Operation 的團隊更容易接手維護你的服務,Developer 也能更專注把精力用在核心的業務上。
這次我會重構先前的範例程式,進一步的擴大 “Container Driven Development” 的概念,假設將來 “一定” 會用 container 的方式部署。同樣的來看看,你可以如何建構這樣的 application?
會寫這篇實在有點意料之外,原本我只是想寫 service discovery 使用 consul 的應用案例啊,為了配合我之前推廣的 CDD (Container Driven Development, 容器驅動開發) 的想法,所有的服務開發,只要搭配 container 就都能簡化成 console application 模式就好,結果過程就碰到這個坑…。解決的過程中,也意外挖出不少 google 不到的細節,加上這個問題沒搞定之前,我要寫的內容跟範例實在寫不下去啊.. 於是就多了這篇…
Windows 畢竟是個以 GUI 竄起來的 OS, 有很多東西還是根深蒂固的綁在 windows 上。這次碰到的問題最後還是搬出 windows message, 視窗的運作基礎才解決掉的, 感覺繞了點遠路, 我也擔心跟 windows form 這麼龐大的機制綁住了,會產生很多不必要的相依性? 如果你知道有更好的做法,麻煩留個言指點一下~ :)