2017-01-16 62 views
0

我目前正在執行一項計劃任務,該任務在我的Spring Web應用程序的幕後運行。該任務使用cron調度程序在每晚的午夜執行,併爲我的門戶清理未使用的應用程序(我的站點允許用戶創建一個應用程序來填寫,如果他們在30天內不訪問該表單,我的背景任務將從我們的數據庫中刪除它,並通知用戶如果需要使用電子郵件創建新表單)。在我的測試環境中,一切都很好,而且我已準備好轉向QA。阻止發送兩封電子郵件的負載平衡服務器環境

但是,我的下一個環境使用兩個負載平衡的服務器來處理請求。這是一個問題,因爲cron調度程序和我的輪詢任務在兩臺服務器上同時運行。雖然讀取/寫入數據庫不會成爲問題,但問題在於將通知電子郵件發送給應用程序用戶。沒有任何輪詢鎖,兩封電子郵件有可能被生成和發送,我想避免這種情況。通常,我們將使用SQL存儲過程並在我們的數據庫中有一個字段用於鎖定,然後在調用輪詢代碼時設置/釋放,因此只有一個輪詢實例將被執行。但是,通過我的新輪詢任務,我們沒有任何可用的字段,所以我正在嘗試使用SPRING解決方案。我發現這個資源在線:

http://www.springframework.net/doc-latest/reference/html/threading.html

而作爲

Semaphore _pollingLock = new Semaphore(1); 
_pollingLock.aquire(); 

try { 
    //run my polling task 
} 
finally { 
    //release lock 
} 

我想使用它。但是,我不知道這是否會只是確保二審後執行,或跳過第二個實例並永遠不會執行。或者,這種解決方案甚至不適合,並有更好的解決方案。再次,我使用Spring java框架,因此任何存在的解決方案都是我最好的選擇。

+1

信號量將在線程之間進行同步,而不是在不同機器上的進程之間進行同步。根據您的數據庫和事務隔離級別,您可以使用阻塞式讀取,以便第二個進程無法讀取第一個進行更新的行。 –

+0

@SergioMontoro我們正在尋找這個解決方案,謝謝! – user3334871

回答

0

我們過去處理過這類問題的兩種方式都是從指定我們的集羣服務器之一作爲負責特定任務的人(比如發送電子郵件或運行作業)開始的。

在一個解決方案中,我們在所有集羣服務器上設置一個JVM參數,用於標識應該運行進程的服務器的名稱。例如-DemailSendServer = clusterMember1

在另一個解決方案中,我們僅僅在此指定服務器啓動時提供了一個JVM參數。例如-DsendEmailFromMe = true

在這兩種情況下,您都可以在流程中添加一小段代碼,根據啓動參數的值或存在情況進行關閉。

我發現第二個選項更簡單,因爲參數的存在足以讓進程運行。在第一種解決方案中,您必須將當前服務器名稱與參數的值進行比較。

我們對Spring Batch沒有做太多的工作,但是我認爲還有一種方法可以將批量配置爲在羣集內的單個服務器上運行作業。

+0

感謝您的回答!不幸的是,這個環境不是服務器集羣,兩者之間唯一共享的就是數據庫。所以在一個環境中設置的任何東西都不可能被另一個環境所達到(在與一個比我更熟悉基礎結構的團隊成員諮詢之後,我意識到了這一點)。 – user3334871