2015-01-03 79 views
1

我在想什麼是將更新部署到(MVC)Go web應用程序的最佳實踐。想象一下以下情形:更新Go web應用程序的最佳實踐

1)代碼和測試我轉到Web應用程序

2)部署更新的一些變化,沒有任何人目前正在使用以前的版本被打斷。

我不知道如何確保點2)可以被覆蓋 - 當有人向服務器發送請求並且在此刻重建/重新啓動它時,他會收到錯誤 - 即使請求只是使用我沒有觸及或向後兼容的代碼的一部分,或者如果我只是添加了一個新的請求處理程序。

也許我錯過了一些微不足道的或衆所周知的模式,因爲我只是在學習過程中,我以前的Web應用程序是ASP.NET或PHP應用程序,因爲我沒有這個問題需要在代碼更改時重新啓動Web服務器。

回答

1

這不僅僅是一起去的問題,但總的來說,我們可以把問題分成兩個獨立的:

  1. 確保當前請求都不會終止,影響用戶體驗。

  2. 確保沒有無法處理新請求的停機時間。

第一個是容易解決:你剛纔不猛烈殺你的服務器,而是讓它退出,從而導致了「排水階段」,在它不接受新的請求,只完成了當前正在運行的請求,並退出。這可以通過聽信號來完成,例如將應用程序輸入特殊狀態。

由於默認的http服務器不支持將其關閉,因此這並不重要,但您可以使用net.Listener啓動服務器,然後在時間到期時保留對其的引用。

現在,只做一個方法然後再次啓動服務會導致新的請求在接收時不被接受,而且我們都知道在極端情況下這可能需要幾秒鐘的時間。

因此,我們需要的是服務器的另一個實例已經在使用新代碼運行,即使舊的代碼沒有響應新的請求,對吧?這可以通過多種方式來完成:

  1. 擁有多臺服務器,並在它們上面負載平衡器,允許一個(或多個)服務器,而我們重新開始另取負載。這是最簡單的方法,也是大多數人做這件事的方式。如果您需要N臺服務器來承擔您的用戶負載,那麼只需保持N + 1並一次重新啓動一臺服務器。

  2. 使用套接字共享技巧。在較新的Linux內核中,許多進程可以在同一個端口上監聽和接受。你所做的只是啓動新實例,然後告訴舊實例完成並退出。這樣就沒有停頓。這是通過在監聽套接字上設置SO_REUSEPORT來完成的。

  3. 以上可以準備發貨解決方案,如艾因霍恩,與你的所有細節涉及自動化,看到https://github.com/stripe/einhorn

  4. 另一種方法是在這個博客中記載:http://blog.nella.org/?p=879

+1

這使我指出了正確的方向。我找到的2個鏈接可能會有所幫助:https://github.com/mailgun/manners(優雅關機),也許https://github.com/rcrowley/goagain(無宕機 - 重新啓動)。 – Compufreak

+1

@Compufreak禮儀看起來不錯。我不認爲我會親自使用goagain,而是使用Einhorn或LB方法(目前我正在使用它)。 –

相關問題