创建定制顾问程序

定制顾问程序是以类文件形式提供的一小段 Java 代码,由负载均衡器基本代码调用以确定服务器上的负载。基本代码提供了所有必要的管理服务,包括启动和停止定制顾问程序的实例、提供状态和报告、将历史记录信息记录在日志文件中以及向管理器组件报告顾问程序结果。

当负载均衡器基本代码调用定制顾问程序时,将执行下列步骤。

  1. 负载均衡器基本代码打开与服务器的连接。
  2. 如果打开了套接字,那么基本代码调用所指定顾问程序的 GetLoad 函数。
  3. 顾问程序的 GetLoad 函数执行用户为评估服务器的状态而定义的步骤,包括等待服务器的响应。该函数在接收到响应时终止执行。
  4. 负载均衡器基本代码关闭与服务器的套接字并向管理器报告负载信息。根据定制顾问程序是以正常方式还是以替换方式运行,在 GetLoad 函数终止后,基本代码有时会执行其他计算。

正常方式和替换方式

可以将定制顾问程序设计为以正常方式或替换方式与负载均衡器交互。

将在定制顾问程序文件中以构造方法中参数的形式指定运行方式选项。(每个顾问程序根据其设计仅以其中一种方式运行。)

在正常方式下,定制顾问程序与服务器交换数据,而基本顾问程序代码则对该交换进行计时并计算负载值。然后基本代码向管理器报告此负载值。定制顾问程序返回值零以指示成功,或返回负值以指示发生了错误。

要指定正常方式,请将构造函数中的替换标志设置为 false

在替换方式下,基本代码不执行任何计时测量。定制顾问程序代码根据其唯一需求执行所指定的任何操作,然后返回实际负载数字。基本代码接受负载数字并将其不作改变地向管理器报告。要获取最佳效果,请将负载数字在 10 与 1000 之间进行常规调整,10 表示快速服务器,1000 表示慢速服务器。

要指定替换方式,请将构造函数中的替换标志设置为 true

顾问程序命名约定

定制顾问程序文件名必须遵循格式 ADV_名称.java,其中名称是您为顾问程序选择的名称。完整名称必须以大写字母的前缀 ADV_ 开头,并且所有后续字符都必须为小写字母。小写字母的要求确保运行顾问程序的命令不区分大小写。

根据 Java 约定,文件中定义的类的名称必须与文件的名称匹配。

编译

必须使用 Java 语言编写定制顾问程序并且使用与负载均衡器代码相同级别的 Java 编译器编译这些顾问程序。要检查系统上 Java 的版本,请从 install_path/java/bin 目录运行以下命令:

java -fullversion

如果当前目录不是您的路径的一部分,那么需要指定应该从当前目录运行 Java 以确保获得正确的版本信息。在这种情况下,请从 install_path/java/bin 目录运行以下命令:

./java -fullversion

编译期间将引用下列文件:

编译期间,classpath 环境变量必须指向定制顾问程序文件和基类文件。编译命令可能具有以下格式:对于 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 操作系统,语法是类似的。

运行定制顾问程序

要运行定制顾问程序,必须首先将顾问程序的类文件复制到负载均衡器机器上的 lib/CustomAdvisors/ 子目录。对于名为 myping 的定制顾问程序,文件路径为 install_path/servers/lib/CustomAdvisors/ADV_myping.class

配置负载均衡器、启动其管理器功能并发出启动定制顾问程序的命令。将通过名称来指定定制顾问程序,不包括 ADV_ 前缀和文件扩展名:

dscontrol advisor start myping port_number

命令中指定的端口号是顾问程序将在其上打开与目标服务器的连接的端口。

必需的例程

像所有顾问程序一样,定制顾问程序扩展名为 ADV_Base 的顾问程序基类的功能。顾问程序基类执行顾问程序的大多数功能,例如向管理器报告负载以在管理器的权重算法中使用。顾问程序基类还执行套接字连接和关闭操作,并提供发送和接收方法供顾问程序使用。顾问程序仅用于在正被调查的服务器的指定端口上发送和接收数据。顾问程序基类中提供的 TCP 方法将定时计算负载。顾问程序基类的构造函数中的一个标志将使用顾问程序返回的新负载覆盖现有负载(如果希望这样的话)。

注:
根据构造函数中设置的值,顾问程序基类以指定的时间间隔将负载提供给权重算法。如果顾问程序尚未完成处理并且无法返回有效负载,那么顾问程序基类使用先前报告的负载。

顾问程序具有下列基类方法:

本节后面提供了关于这些必需例程的详细信息。

搜索顺序

将在搜索了本机顾问程序或标准顾问程序之后调用定制顾问程序。如果负载均衡器在标准顾问程序列表中找不到指定的顾问程序,那么它将查找定制顾问程序列表。可以在 WebSphere® Application Server 负载均衡器 Administration Guide 中找到有关使用顾问程序的其他信息。

命名和文件路径

请记住定制顾问程序名称和路径的下列要求。

定制顾问程序方法和函数调用

构造函数(由顾问程序基件提供)

public <advisor_name> (
        String sName;
        String sVersion;
        int iDefaultPort;
        int iInterval;
        String sDefaultLogFileName;
        boolean replace
)
sName
定制顾问程序的名称。
sVersion
定制顾问程序的版本。
iDefaultPort
未在调用中指定端口号时要用于与服务器联系的端口号。
iInterval
顾问程序将查询服务器的时间间隔。
sDefaultLogFileName
需要此参数,但未使用此参数。唯一可接受的值是空字符串 ""
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 套接字,该套接字表示已对当前服务器打开以用于通信的套接字。

此函数不带任何参数。

getInterval()

getInterval 函数返回顾问程序时间间隔,即顾问程序循环之间的秒数。除非使用 dscontrol 命令在运行时修改了此值,否则此值等于定制顾问程序的构造函数中设置的缺省值。

返回值是一个 Java 整数。此函数不带任何参数。

caller.getLatestLoad()

getLatestLoad 函数允许定制顾问程序获取给定服务器对象的最新负载值。负载值由顾问程序基本代码和管理器守护程序保存在内部表中。

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

三个自变量共同定义一个服务器对象。

clusterId
要获取其当前负载值的服务器对象的集群标识。此自变量必须是 Java 字符串。
port
要获取其当前负载值的服务器对象的端口号。
serverId
要获取其当前负载值的服务器对象的服务器标识。此自变量必须是 Java 字符串。

返回值是一个整数。

如果要使一个协议或端口的行为依赖于另一个协议或端口的行为,那么此函数调用很有用。例如,您可以在禁用了特定应用程序服务器的定制顾问程序中使用此函数调用(如果在该同一台机器上禁用了 Telnet 服务器)。

caller.receive()

receive 函数从套接字连接中获取信息。

caller.receive(StringBuffer *response)

参数 response 是一个字符串缓冲区,检索到的数据将放置在该缓冲区中。此外,此函数还会返回一个具有下列含义的整数值:

caller.send()

send 函数使用已建立的套接字连接通过指定的端口将数据包发送到服务器。

caller.send(String command)

参数 command 是包含要发送到服务器的数据的字符串。此函数返回一个具有下列含义的整数值:

suppressBaseOpeningSocket()

suppressBaseOpeningSocket 函数调用允许定制顾问程序指定基本顾问程序代码是否为定制顾问程序打开与服务器的 TCP 套接字。如果顾问程序不使用与服务器的直接通信来确定其状态,那么可能不需要打开此套接字。

只能发出此函数调用一次,并且必须从 ADV_AdvisorInitialize 例程发出。

此函数不带任何参数。