0

我最近將Symfony項目從手動縮放EC2環境移至Elastic Beanstalk,並且我偶然發現了一個問題。Amazon ElasticBeanstalk中的單實例cronjob

我有一個Cron作業,抓住了一堆已滿的訂閱,並嘗試創建訂單並對它們進行收費,因此這項工作只能在單個服務器上運行,這一點非常重要,因爲它在批處理中抓取它們,如果有重複的Cron正在運行,它將導致相同訂閱的多項費用。

在手動擴展環境中,我只有一臺主服務器,它有一個crontab並運行了子服務器,但在這裏看起來並不可行。

有關如何在沒有主服務器的自動擴展環境中進行設置的任何建議?

我已經看過JMSJobQueueBundle,但它似乎也依賴於只運行crontab的單個實例的主管,這將在自動擴展環境中重複。

我最好是有一個外部服務器每隔X分鐘對我的API進行ping操作,並在單個實例上啓動它的ping工作?這似乎引發了另一個失敗點。

回答

2

就像一個警告,你試圖解決的問題不是一個微不足道的問題。

有幾個選項:

  1. 如果你連接到MySQL數據庫,掌握在事務開始時的鎖(https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock),並在年底解除鎖定。這會阻止多個cronjob同時運行代碼。只有在SQL中處理所有內容時纔有效。

  2. 如上所述,您可以使用AWS Lambda + CloudWatch Events每x分鐘觸發一次Lambda函數,並且Lambda可以通過http(s)觸發腳本。但是拉姆達並不能保證這樣做只是一次,所以這是不安全的。

  3. 使用一種服務,您可以獲取分佈式鎖(例如etcd,consul,redis,...)並以與1相似的方式實現,而不僅僅是在您的MySQL數據庫中。儘管如此,你仍然可以或者真的只有一次。

  4. 把cronjob放在一個單獨的ec2實例上,你知道它只存在一次(如果這個ec2實例發生故障,什麼都不會運行,但據我瞭解你的要求,這不是問題,因爲腳本可以在以後運行15分鐘,仍與所有工作趕上。

在分佈式系統中的更「現代」的方法是使你的行動冪等。

+0

我將試圖建立一個工人。 –