本文探討兩個相關問題:

  • 在多伺服器環境中,如何安全地關閉單一伺服器?
  • 要在多伺服器負載平衡的環境中運作,需要對應用程式做哪些調整?

背景:擴增容易,縮減困難

在需要多台伺服器來應對使用者需求的環境中,擴增伺服器數量(Scale Up)相對容易——新伺服器上線後,負載平衡器就會開始分配流量給它。

縮減伺服器數量(Scale Down / SpinDown)則複雜得多。這與「會話綁定請求處理」和「無會話請求處理」之間的根本差異有關:

  • 會話綁定(Session-bound):GUI Genero 應用程式和黏性 Web 服務(Sticky Web Services)採用此模式。同一個客戶端的連續請求,必須到達同一台伺服器上的同一個 fglrun 程序。
  • 無會話(Session-less):非黏性 Web 服務採用此模式,每個請求都是無狀態的,可以到達任何可用的 fglrun 程序。

對於透過負載平衡器的會話綁定請求,管理員應設定 Session 持久性(Session Persistence),例如 nginx-plus 的 session-persistence 設定。

核心問題:有增必有減

「有增就有減」。當使用者需求降低,需要關閉伺服器時,管理員面臨的挑戰是:如何處理仍在該伺服器上執行中的 fglrun 程序?

gasadmin 工具提供以下幾種處理方式:

  • 啟用/停用應用程式和服務,阻止新的請求被分配到即將關閉的伺服器
  • 使用 list-sessionidle-timeclose-sessionclose-all-session 等指令監控並管理閒置的 Session
  • 使用 send-message 指令提前通知使用者伺服器即將關閉

長時間執行程序的挑戰

阻礙伺服器順利關閉的主要因素是長時間執行的程序,這分為兩類:

  1. 合理的長時間程序:月結、年結等批次作業,本來就需要長時間執行。
  2. 非預期的長時間程序:使用者離開座位後沒有登出,程式仍在等待輸入。

這兩種情況都會讓伺服器無法順利關閉。

建議解決方案

批次作業:改為背景執行

對於月結、年結等真正需要長時間執行的批次程序,應改為背景模式執行,而不是顯示 GUI 進度畫面:

RUN "export FGLGUI=0; fglrun program-name" WITHOUT WAITING

並將這類批次作業排程到最後一台要關閉的伺服器上執行,這樣其他伺服器就可以先行關閉。

GUI 應用程式:設定閒置逾時

對於 GUI 應用程式,實作 ON IDLEAUTO_LOGOUT 機制,在程式長時間閒置後(例如 30 分鐘)自動終止。這可以避免「使用者離開但程式仍在執行」的問題。

黏性 Web 服務:設定 KEEP_ALIVE

對於黏性 Web 服務,在 .xcf 檔案中設定 KEEP_ALIVE 元素,讓 fglrun 程序在請求停止後自動關閉,而不是一直等待下一個請求。

Genero 的限制:無法跨伺服器遷移程序

與某些其他平台不同,Genero 目前無法將 fglrun 程序從一台伺服器遷移到另一台伺服器。原因是資料庫連線、游標(Cursor)、交易(Transaction)和檔案句柄(File Handle)等資源都是綁定在特定程序上的,無法跨機器移植。

因此,正確的策略是事前預防:確保應用程式在閒置狀態(特別是登入/密碼畫面,或只讀查詢介面)時盡量釋放資源,減少對特定伺服器的依賴。

重點摘要

  • 縮減問題(SpinDown Problem):需求降低時,關閉伺服器需要妥善處理其上仍在執行的程序。
  • 並非 Genero 特有:任何有狀態(Stateful)的框架都會遇到相同問題。
  • 可用工具:gasadmin 提供監控、停用、通知和關閉 Session 等功能,搭配負載平衡器控制使用。
  • 緩解策略:避免不必要的長時間執行程序;批次作業改為背景執行(不含 UI);實作閒置逾時機制;設計應用程式以盡量減少不必要的持續執行時間。

伺服器終究可以關閉——關鍵在於給予使用者充足的通知,確保不會有工作遺失。

原文:https://4js.com/ask-reuben/ig-305/  ·  有任何 Genero 技術問題或翻譯疑問,歡迎來信 support@t100.app