在Debricked,咱們已經將Symfony用於咱們的Web後端已有一段時間了。它爲咱們提供了很好的服務,當他們在Symfony 4.1中宣佈Messenger組件時,咱們很想嘗試一下。從那時起,咱們就使用該組件進行異步排隊電子郵件。php
最近,出於性能緣由,須要將咱們從GitHub集成中收到的GitHub事件的處理從Web後端分離到單獨的微服務,以分開處理。咱們決定利用Messenger組件提供的生產者/消費者模式,由於它使咱們能夠將各類事件異步地分派到隊列中,而後當即將該事件確認給GitHub。html
可是,與發送電子郵件相比,處理一些GitHub事件可能很耗時。咱們也沒法控制什麼時候發生這些事件,所以負載既不可預測又不規則-咱們須要自動縮放使消費者。git
因爲咱們已經將大部分基礎架構部署到Google Cloud上的Kubernetes,所以有必要嘗試爲咱們的消費者利用它。 Kubernetes提供了一種稱爲Horizontal Pod Autoscaler的工具,它可讓您根據某些度量標準自動縮放您的Pod。github
自動縮放器具備一個內置的指標,即CPU指標。它使咱們能夠跨Pod設置目標CPU負載,而後Kubernetes將自動調整Pod的數量以匹配目標。咱們將使用此指標來確保咱們始終有合理數量的Pod,能夠運行咱們的消費者。後端
得出結論,Kubernetes能夠幫助咱們,咱們如今須要一個合適的Docker鏡像來運行咱們的Pod。咱們將消費者鏡像基於咱們的基礎鏡像,該基礎鏡像基於Debian,幷包含咱們的後端邏輯,包括GitHub事件消費者/消息處理程序的邏輯。bash
Symfony建議使用一種名爲「Supervisor」的工具來控制消費者的執行,所以咱們將其添加到鏡像中,並在Docker的CMD指令中啓動它,請參見下面的示例代碼:網絡
若是仔細看,咱們還會添加兩個與運行Supervisor(d)有關的文件。這些文件以下所示:架構
這是一個至關標準的Supervisor配置,其中有幾項值得注意。咱們正在執行一個bash腳本,該腳本又將以狀態代碼37退出,在下一部分中進一步介紹該腳本,或者使用咱們的GitHub事件使用者執行Messenger組件的消耗命令。咱們還將Supervisor配置爲在乎外失敗時自動重啓,意外失敗是任何狀態代碼都不爲37。併發
在咱們的案例中,因爲負載受網絡IO的限制,咱們將同時運行大量使用者(70個)。經過同時運行70個消費者,咱們能夠徹底飽和咱們的CPU。這是HPA的CPU指標正常工做所必需的,由於不然負載會過低-無論隊列有多長,縮放都會卡在配置的最小副本上。app
當HPA決定了負載太高啓動新的Pod。因爲Messenger組件的異步特性,咱們無需擔憂諸如競態條件之類的併發問題。它能夠在具備多個消費者的狀況下開箱即用,所以增長的pod/消費者數量不會引發任何問題,可是當負載過低且縮放器決定縮小實例時會發生什麼呢?
默認狀況下,若是自動縮放器決定再也不須要它時,它將忽然終止正在運行的pod。這會致使消費者出現問題,由於它可能正處於處理郵件的過程當中。咱們須要一種方法來正常關閉Pod,使用咱們當前正在處理的消息,而後退出。
在Dockerfile的上一節中,您可能已經注意到咱們將名爲pre_stop.sh
的文件複製到了鏡像中。該文件以下所示:
執行時,此bash腳本將建立一個/tmp/debricked-stop-work.txt
文件。因爲該腳本還調用php/app/bin/console messenger:stop-workers
,所以它將優雅地中止當前的工做程序/消費者,從而致使Supervisord從新啓動supervisord_githubeventconsumer.sh
。腳本從新啓動後,因爲存在/tmp/debricked-stop-work.txt,它如今將當即以狀態碼37退出。反過來致使Supervisor退出,由於37是咱們的預期退出狀態碼。
一旦Supervisor退出,做爲Supervisor的Docker鏡像就會成爲咱們的CMD,而且pre_script.sh也將終止,由於supervisord_githubeventconsumer.sh在刪除37以前會刪除/tmp /debricked-stop-work.txt
。咱們已經實現了正常關機!
可是什麼時候執行「pre_script.sh」?您可能會問本身。咱們將在Kubernetes容器的PreStop
生命週期事件中執行它。
每當容器即將終止時(例如,由自動縮放器終止時),都會發生此事件。這是一個阻塞事件,這意味着在完成該腳本以前,不會刪除容器,這正是咱們想要的。
要配置生命週期事件,咱們只須要將幾行代碼添加到咱們的部署配置中,如如下示例所示:
不知所措?這是關閉流程的示意圖:
在本文中,咱們學習瞭如何根據負載來動態擴展Symfony Messenger消費者,包括正常關閉它們。以經濟有效的方式致使消息的高吞吐量。