本頁面說明如何從第一代 Go 執行階段遷移至第二代。如要將第二代應用程式升級為最新支援的 Go 版本,請參閱「升級現有應用程式」。
我們已於 2024 年 1 月 30 日停止支援 Go 1.11。現有的 Go 1.11 應用程式將繼續執行並接收流量。不過,如果應用程式使用已停用支援的日期後的執行階段,App Engine 可能會阻止重新部署該應用程式。建議您按照本頁面中的指南,改用最新的 Go 支援執行階段。
遷移至支援的第二代 Go 執行階段後,您就能使用最新的語言功能,並透過慣用程式碼建構更具可攜性的應用程式。
第二代執行階段的變更
升級至支援的第二代 Go 執行階段時,請考量下列差異:
為減少執行階段遷移作業的負擔和複雜度,App Engine 標準環境可讓您存取第二代執行階段中的許多舊版套裝服務和 API,例如 Memcache。第二代 Go 應用程式可以透過 Go 版 App Engine SDK 呼叫內含的服務 API,並存取 Go 1.11 執行階段的大部分功能。
您也可以選擇使用 Google Cloud 產品,這些產品提供的功能與舊版套裝服務相似。這些 Google Cloud產品提供專屬的 Cloud 用戶端程式庫 (適用於 Go)。如果是無法在Google Cloud中以獨立產品形式提供的套裝服務 (例如圖片處理、搜尋和訊息傳送),您可以使用第三方供應商或其他解決方法。
如要進一步瞭解如何遷移至非套裝組合服務,請參閱「從套裝組合服務遷移」。
app.yaml
設定檔中部分元素的行為已受到修改。詳情請參閱「app.yaml
檔案的變更」。第二代執行階段的記錄功能會遵循 Cloud Logging 的記錄標準。在第二代執行階段中,應用程式記錄不再與要求記錄綁在一起,而是分開儲存在不同的記錄中。如要進一步瞭解如何在第二代執行階段中讀取及寫入記錄,請參閱記錄指南。
記憶體用量差異
與第一代執行階段相比,第二代執行階段的記憶體使用量基準較高。這可能是由多種因素造成,例如不同的基礎映像檔版本,以及兩個世代計算記憶體用量的方式不同。
第二代執行階段會將執行個體記憶體用量計算為應用程式程序使用的用量總和,以及記憶體中動態快取的應用程式檔案數量。為避免記憶體密集型應用程式因超出記憶體限制而導致執行個體關閉,請升級至記憶體較多的執行個體類別。
CPU 用量差異
在執行個體冷啟動時,第二代執行階段可看到較高的 CPU 使用率基準。視應用程式的縮放設定而定,這可能會產生非預期的副作用,例如,如果應用程式已設為根據 CPU 使用率進行縮放,則執行個體數量可能會高於預期。為避免發生這個問題,請查看並測試應用程式縮放設定,確保可用的執行個體數量。
要求標頭差異
第一代執行階段允許將含有底線的請求標頭 (例如 X-Test-Foo_bar
) 轉送至應用程式。第二代執行階段會將 Nginx 導入主機架構。因此,第二代執行階段會自動移除含有底線 (_
) 的標頭。為避免應用程式發生問題,請避免在應用程式要求標頭中使用底線。
app.yaml
檔案的變更
app.yaml
設定檔中部分元素的行為已受到修改:
元素 | 變更類型 | 說明 |
---|---|---|
app_engine_apis |
使用舊版套裝組合服務的應用程式必須具備 | 如果您想存取
第二代執行階段的舊版服務套裝組合,則必須設為 true 。 |
login |
如果 app_engine_apis 為 true ,則支援 |
如果您未使用舊版套裝服務來支援第二代執行階段,請使用這些 替代方法來驗證使用者。 |
runtime |
已修改 |
變更 runtime 元素,以指定第二代執行階段。 |
詳情請參閱 app.yaml
參考資料。
建立 main
套件
您的服務至少要在一個來源檔案內包含 package main
陳述式。
App Engine 舊版套裝組合服務
如果您的服務使用第二代執行階段的舊版套裝服務:
您的服務只能使用 v2 (
google.golang.org/appengine/v2
) 套件。使用舊版 v1 (google.golang.org/appengine
) 套件會導致錯誤。在
main()
函式中,請呼叫appengine.Main()
,而非http.ListenAndServe()
。這可確保user
和appengine
API 可存取目前的要求情境。
編寫 main 套件
如果您的服務尚未包含 main
套件,請新增 package main
陳述式並編寫 main()
函式。main()
函式「至少」應:
讀取
PORT
環境變數並呼叫http.ListenAndServe()
函式:
註冊 HTTP 處理常式
您可以透過下列其中一個選項註冊 HTTP 處理常式:
- 建議使用的方法為手動將所有
http.HandleFunc()
呼叫從您的套件移至main
套件中的main()
函式。 或者,將應用程式的套件匯入您的
main
套件,確保每個init()
函式 (當中包含http.HandleFunc()
的呼叫) 會在啟動時執行。您可以透過下列 bash 指令碼找到使用
http.HandleFunc()
呼叫的所有套件,並將輸出內容複製到main
套件的import
區塊:gp=$(go env GOPATH) && p=$(pwd) && pkg=${p#"$gp/src/"} && find . -name "*.go" | xargs grep "http.HandleFunc" --files-with-matches | grep -v vendor/ | grep -v '/main.go' | sed "s#\./\(.*\)/[^/]\+\.go#\t_ \"$pkg/\1\"#" | sort | uniq
建立檔案結構
Go 要求每個套件都必須要有自己的目錄。您可以在專案的 app.yaml
檔案中使用 main:
,來通知 App Engine 您 main
套件的位置。舉例來說,如果您應用程式的檔案結構如下:
myapp/ ├── app.yaml ├── foo.go ├── bar.go └── web/ └── main.go
您的 app.yaml
檔案就會包含:
main: ./web # Relative filepath to the directory containing your main package.
如要進一步瞭解 main
標記,請參閱 app.yaml
參考資料。
將檔案移至您的 GOPATH
使用下列指令找出您的 GOPATH
:
go env GOPATH
請將所有相關檔案和匯入內容移至 GOPATH
。如果使用相對匯入 (例如 import ./guestbook
),請將匯入路徑更新為完整路徑:import github.com/example/myapp/guestbook
。