建立自訂顧問

自訂顧問是一小段 Java 程式碼,以類別檔的形式提供,Load Balancer 基本程式碼會呼叫它來決定伺服器上的負載。基本程式碼提供所有必要的管理服務,包括啟動及停止自訂顧問的實例、提供狀態和報告、在日誌檔中記錄歷程資訊,以及向管理程式元件報告顧問結果。

當 Load Balancer 基本程式碼呼叫自訂顧問時,會發生下列步驟。

  1. Load Balancer 基本程式碼會開啟與伺服器機器的連線。
  2. 如果 socket 開啟,基本程式碼會呼叫指定顧問的 GetLoad 函數。
  3. 顧問的 GetLoad 函數會執行使用者定義來評估伺服器狀態的步驟,包括等待伺服器的回應。 當接收到回應時,此函數就會終止執行。
  4. Load Balancer 基本程式碼會關閉伺服器的 socket,並向管理程式報告負載資訊。 視自訂顧問是以標準模式或取代模式操作而定,基本程式碼有時候會在 GetLoad 函數終止之後執行其他計算。

標準模式和取代模式

自訂顧問可設計為以標準模式或取代模式來與 Load Balancer 互動。

作業模式的選擇是指定在自訂顧問檔案中,作為建構子方法的一個參數。 (根據其設計,每一個顧問只在這其中一個模式下操作。)

在標準模式中,自訂顧問會與伺服器交換資料,且基本顧問程式碼會計算交換時間及計算負載值。 然後基本程式碼會向管理程式報告此負載值。 自訂顧問會傳回零值指出成功,或傳回負值指出錯誤。

如果要指定標準模式,請將建構子中的取代旗標設為 false

在取代模式下,基本程式碼不執行任何計時測量。 自訂顧問程式碼會根據其特有的需求執行任何指定的作業,然後傳回實際的負載數。 基本程式碼接受此負載數,並原封不動地報告給管理程式。 為獲得最佳結果,請將負載數正規化為介於 10 到 1000 之間,其中 10 代表快速伺服器,1000 代表慢速伺服器。

如果要指定取代模式,請將建構子中的取代旗標設為 true

顧問命名慣例

自訂顧問檔名必須遵循 ADV_name.java 格式,其中 name 是您選擇的顧問名稱。完整名稱必須以大寫字母的字首 ADV_ 作為開頭,所有後續字元則必須為小寫字母。 小寫字母可確保執行顧問的指令不區分大小寫。

根據 Java 使用慣例,定義在此檔案內的類別名稱必須符合檔案的名稱。

編譯

您必須以 Java 語言撰寫自訂顧問,並以 Java 編譯器編譯它們,其層次與 Load Balancer 程式碼相同。如果要檢查您系統上的 Java 版本,請從 install_path/java/bin 目錄執行下列指令:

java -fullversion

如果現行目錄不是您路徑的一部分,您需要指定 Java 從現行目錄執行,以確保您取得正確的版本資訊。 在此情況下,請從 install_path/java/bin 目錄執行下列指令:

./java -fullversion

在編譯期間會參照下列檔案:

在編譯期間,類別路徑環境變數必須同時指向自訂顧問檔案和基礎類別檔案。 編譯指令可能有下列格式:若為 UNIX Windows 系統,範例編譯指令如下:

 install_path/java/bin/javac -classpath /opt/ibm/edge/lb/servers/lib/ibmlb.jar ADV_name.java

其中:

編譯的輸出是類別檔,例如,ADV_name.class。在啟動顧問之前,請將類別檔複製到 install_path/servers/lib/CustomAdvisors/ 目錄。

註:
您可以在一個作業系統上編譯自訂顧問,然後在另一個作業系統上執行。 例如,您可以在 Windows 系統上編譯顧問,以二進位格式將產生的類別檔複製到 Linux 機器,並在該處執行自訂顧問。若為 AIX、HP-UX、Linux 和 Solaris 作業系統,其語法類似。

執行自訂顧問

如果要執行自訂顧問,您必須先將顧問的類別檔複製到 Load Balancer 機器上的 lib/CustomAdvisors/ 子目錄。 例如,若自訂顧問命名為 myping,則檔案路徑為 install_path/servers/lib/CustomAdvisors/ADV_myping.class

配置 Load Balancer,啟動其管理程式函數,並發出指令來啟動自訂顧問。 自訂顧問是以其名稱指定,不包括 ADV_ 字首和副檔名:

dscontrol advisor start myping port_number

該指令中指定的埠號是顧問與目標伺服器開啟連線時所用的埠。

必要常式

和所有顧問一樣,自訂顧問會延伸顧問基礎類別 (ADV_Base) 的功能。顧問基本程式執行大部分顧問函數,例如向管理程式回報負載,以使用於管理程式的加權演算法中。 顧問基本程式也執行 socket 連接和關閉作業,並提供傳送和接收方法供顧問使用。 顧問只用來針對探索中的伺服器傳送及接收指定埠上的資料。 顧問基本程式內提供的 TCP 方法會預定計算負載。 若有需要,顧問基本程式之建構子內的旗標,可使用從顧問傳回的新負載改寫現有的負載。

註:
根據建構子所設定的值,顧問基本程式會按照指定的間隔提供負載給加權演算法。 如果顧問未完成處理,且無法傳回有效負載,顧問基本程式便會使用先前報告的負載。

顧問有下列基礎類別方法:

此章節後面有關於這些必要常式的詳細資料。

搜尋順序

在搜尋原生或標準顧問之後,會呼叫自訂顧問。 如果 Load Balancer 在標準顧問清單中找不到指定的顧問,它會查看自訂顧問清單。 如需使用顧問的相關資訊,請參閱 WebSphere® Application Server Load Balancer 管理手冊

命名和檔案路徑

請記住自訂顧問名稱和路徑的下列需求。

自訂顧問方法和函數呼叫

建構子(由建構子基本程式提供)

public <advisor_name> (
        String sName;
        String sVersion;
        int iDefaultPort;
        int iInterval;
        String sDefaultLogFileName;
        boolean replace
)
sName
自訂顧問的名稱。
sVersion
自訂顧問的版本。
iDefaultPort
如果在呼叫中未指定埠號,這便是用來聯絡伺服器的埠號。
iInterval
顧問查詢伺服器的間隔。
sDefaultLogFileName
這是必要參數,但不會使用到。唯一可接受的值是空值字串 ""
replace
此顧問是否在 replace 模式下運作。可能值如下:

ADV_AdvisorInitialize()

void  ADV_AdvisorInitialize()

提供此方法是為了執行自訂顧問可能需要的起始設定。 此方法是在顧問基本模組啟動之後呼叫。

在許多案例中,包括標準顧問在內,都不使用此方法,其程式碼只由 return 陳述式組成。 此方法可用來呼叫 suppressBaseOpeningSocket 方法,只有在這個方法內它才有效。

getLoad()

int getLoad(
        int iConnectTime;
        ADV_Thread *caller
)
iConnectTime
完成連線所花費的時間長度(毫秒)。此負載測量是由顧問基本程式碼執行,並傳遞至自訂顧問程式碼,在傳回負載值時後者可使用或忽略該測量。 如果連線失敗,此值會設為 -1。
caller
顧問基礎類別的實例,其中提供顧問基本方法。

可用於自訂顧問的函數呼叫

下列幾節所說明的方法或函數可從自訂顧問呼叫。 這些方法受顧問基本程式碼支援。

這些函數呼叫當中,有些可以直接發出,例如 function_name(),有些則需要字首 callerCaller 代表基本顧問實例,它支援所要執行的自訂顧問。

ADVLOG()

ADVLOG 函數容許自訂顧問將文字訊息寫入顧問基本日誌檔中。 其格式如下:

void  ADVLOG  (int logLevel, String message)
logLevel
訊息寫入日誌檔時的狀態層次。顧問日誌檔由階段組成;最緊急的訊息,其狀態層次為 0,越不緊急的訊息得到的數字越高。最詳細的訊息類型,其狀態層次為 5。這些層次用來控制使用者即時接收的訊息類型(dscontrol 指令則用來設定詳細程度)。災難性錯誤一律記載在層次 0。
message
寫入日誌檔的訊息。此參數的值是標準 Java 字串。

getAdvisorName()

getAdvisorName 函數傳回的 Java 字串含有自訂顧問名稱的字尾部分。 例如,對於名稱為 ADV_cdload.java 的顧問,此函數傳回 cdload 值。

此函數不使用參數。

請注意,在顧問的一次實例化期間,此值無法變更。

getAdviseOnPort()

getAdviseOnPort 函數傳回呼叫的自訂顧問執行時的埠號。 回覆值是 Java 整數 (int),且此函數不使用參數。

請注意,在顧問的一次實例化期間,此值無法變更。

caller.getCurrentServerId()

getCurrentServerId 函數傳回 Java 字串,它是現行伺服器的唯一表示法。

一般來說,每次您呼叫自訂顧問時,此值都會變更,因為顧問基本程式碼會連續查詢所有伺服器機器。

此函數不使用參數。

caller.getCurrentClusterId()

getCurrentClusterId 函數呼叫傳回 Java 字串,它是現行叢集的唯一表示法。

一般來說,每次您呼叫自訂顧問時,此值都會變更,因為顧問基本程式會連續查詢所有叢集。

此函數不使用參數。

caller.getSocket()

getSocket 函數呼叫傳回 Java socket,它代表對現行伺服器開啟以進行通訊的 socket。

此函數不使用參數。

getInterval()

getInterval 函數傳回顧問間隔,亦即顧問週期之間的秒數。 除非利用 dscontrol 指令在執行時期修改過此值,否則此值即等於在自訂顧問建構子中設定的預設值。

回覆值是 Java 整數 (int)。此函數不使用參數。

caller.getLatestLoad()

getLatestLoad 函數容許自訂顧問取得給定之伺服器物件的最新負載值。 顧問基本程式碼和管理程式常駐程式會在內部表格中維護負載值。

int caller.getLatestLoad (String clusterId, int port, String serverId)

這三個引數共同定義一個伺服器物件。

clusterId
要取得現行負載值之伺服器物件的叢集 ID。 此引數必須是 Java 字串。
port
要取得現行負載值之伺服器物件的埠號。
serverId
要取得現行負載值之伺服器物件的伺服器 ID。 此引數必須是 Java 字串。

回覆值是整數。

如果您想要使一個通訊協定或埠的行為仰賴另一個通訊協定或埠的行為,則此函數呼叫非常有用。 例如,若同一部機器上的 Telnet 伺服器已停用,您可以在已停用特定 Application Server 的自訂顧問中,使用此函數呼叫。

caller.receive()

receive 函數從 socket 連線取得資訊。

caller.receive(StringBuffer *response)

response 參數是字串緩衝區,所擷取的資料會放置在此。 此外,該函數會傳回具有下列意義的整數值:

caller.send()

send 函數利用指定的埠,使用已建立的 socket 連線將資料封包傳送至伺服器。

caller.send(String command)

command 參數是包含要傳送至伺服器之資料的字串。 該函數會傳回具有下列意義的整數值:

suppressBaseOpeningSocket()

suppressBaseOpeningSocket 函數呼叫容許自訂顧問指定,基本顧問程式碼是否代表自訂顧問在伺服器上開啟 TCP socket。 如果顧問不使用與伺服器的直接通訊來判定其狀態,則可以不需要開啟這個 socket。

此函數呼叫只能發出一次,而且必須從 ADV_AdvisorInitialize 常式發出。

此函數不使用參數。