この版は、以下のプログラムに適用されます。
また、新しい版で明記されていない限り、以降のすべてのリリースおよびモディフィケーションに適用されます。
本マニュアルに関するご意見やご感想は、次の URL からお送りください。今後の参考にさせていただきます。
http://www.ibm.com/jp/manuals/main/mail.html
なお、日本 IBM 発行のマニュアルはインターネット経由でもご購入いただけます。詳しくは
http://www.ibm.com/jp/manuals/ の「ご注文について」をご覧ください。
(URL は、変更になる場合があります)
お客様の環境によっては、資料中の円記号がバックスラッシュと表示されたり、バックスラッシュが円記号と表示されたりする場合があります。
原 典: |
GC31-6919-00 WebSphere Application Server Programming Guide for Edge Components Version 6.1 |
発 行: | 日本アイ・ビー・エム株式会社 |
担 当: | ナショナル・ランゲージ・サポート |
第1刷 2006.5
このセクションでは、本書「WebSphere(R) Application Server Edge Components プログラミング・ガイド」の目的、編成、および規約について説明します。
本書では、WebSphere Application Server、バージョン 6.1 の Edge Components をカスタマイズするために使用できるアプリケーション・プログラミング・インターフェース (API) について説明します。この情報は、プラグイン・アプリケーションを作成したり、その他のカスタマイズを行うプログラマーを対象としています。ネットワーク設計者およびシステム管理者にとっても、この情報は可能なカスタマイズ・タイプの指示として役立つ場合があります。
本書の情報を使用するには、 Java(TM) または C 言語 (使用予定の API に応じる) を使用したプログラミング手順を理解している必要があります。公開された各インターフェースで使用可能なメソッドおよび構造について文書化していますが、独自のアプリケーションの構成方法、ユーザー・システム用のコンパイル方法、および検査方法を知っている必要があります。一部のインターフェースにはサンプル・コードが提供されていますが、このサンプルは独自のアプリケーションを構成するための例としてのみ提供されています。
本書では、以下のような書体およびキー操作の規則を使用しています。
規則 | 意味 |
---|---|
太字 | グラフィカル・ユーザー・インターフェース (GUI) に関しては、太字は、メニュー、メニュー項目、ラベル、ボタン、アイコン、およびフォルダーを示します。また、太字にしないと周りのテキストと混同される恐れがあるコマンド名を強調するためにも使用されます。 |
モノスペース | コマンド・プロンプトから入力する必要のあるテキストを示します。また、モノスペースは、画面上のテキスト、コード例、およびファイルからの引用も示します。 |
イタリック | 指定する必要のある可変値を示します (例: fileName にファイルの名前を指定します)。 イタリックは、強調表示および書名の表示にも使用されます。 |
Ctrl-x | x がキーの名前である場合、制御文字のシーケンスを示します。例えば、 Ctrl-c は、Ctrl キーを押しながら c キーを押すという意味になります。 |
Return | Return、Enter または左矢印が表示されていたキーを指します。 |
% | Linux および UNIX(R) のコマンド・シェル・プロンプト (root 権限を必要としないコマンド用) を示します。 |
# | Linux および UNIX のコマンド・シェル・プロンプト (root 権限を必要とするコマンド用) を示します。 |
C:¥ | Windows のコマンド・プロンプトを示します。 |
コマンド入力 | コマンドを「入力」する「発行」するよう指示されたときは、コマンドを入力してから Return を押します。例えば、「ls コマンドを入力してください」という指示は、コマンド・プロンプトに ls と入力してから Return を押すという意味になります。 |
[ ] | 構文記述内のオプション項目を囲みます。 |
{ } | 構文記述内の、項目を選択する必要があるリストを囲みます。 |
| | 構文記述の中で { } (中括弧) で囲まれた選択項目リストにある項目を区切るために使用されます。 |
... | 構文記述内の省略記号は、前の項目を 1 回以上繰り返すことができることを示します。例にある省略記号は、簡潔にするために例から情報が省略されていることを示します。 |
アクセシビリティ機能は、運動障害または視覚障害など身体に障害を持つユーザーがソフトウェア・プロダクトを快適に使用できるようにサポートします。 WebSphere Application Server、バージョン 6.1 の主なアクセシビリティー機能は次のとおりです。
本書では、WebSphere Application Server の Edge Components に提供されるアプリケーション・プログラム・インターフェース (API) について説明します。 (WebSphere Application Server の Edge Components には、Caching Proxy と Load Balancer が含まれます。) 管理者は提供されるいくつかのインターフェースを使用してインストールをカスタマイズし、Edge Components 相互間の対話方法を変更するか、または他のソフトウェア・システムとの対話を可能にすることができます。
重要: Caching Proxy は、すべての Edge コンポーネントのインストールで使用可能です。ただし、次の例外があります。
本書の API はいくつかのカテゴリーを扱っています。
Caching Proxy にはその処理シーケンスに書き込まれるいくつかのインターフェースがあり、このシーケンスでカスタム処理を標準処理用に追加または置換できます。実行できるカスタマイズには、以下のようなタスクの変更および拡大が含まれます。
カスタム・アプリケーション・プログラムは、Caching Proxy プラグインとしても知られていますが、プロキシー・サーバーの処理シーケンス中の、事前に定義されたポイントで呼び出されます。
Caching Proxy API は、システム機能をインプリメントするために使用されます。例えば、プロキシー・サーバーの LDAP サポートはプラグインとしてインプリメントされます。
インターフェースの詳細については、Caching Proxy APIで説明します。これにはプラグイン・プログラムを使用する プロキシー・サーバー の構成ステップが含まれます。
Load Balancer は、ユーザー独自のアドバイザーを作成することによってカスタマイズできます。アドバイザーはサーバー上で実際のロード測定を実行します。カスタム・アドバイザーがあれば、ロードを測定するためのシステムに関連する、自分で用意したメソッドを使用することができます。これは特に、カスタマイズ済みまたは所有 Web サーバー・システムがある場合に重要です。
カスタム・アドバイザーの作成および使用の詳細については、カスタム・アドバイザーで説明します。これには、アドバイザーのサンプル・コードも含まれます。
上記の API のサンプル・コードは、Edge Components CD-ROM の samples ディレクトリーに入っています。 WebSphere Application Server Web サイト www.ibm.com/software/webservers/appserv/ からこの他のコード・サンプルを入手できます。
このセクションでは、Caching Proxy アプリケーション・プログラミング・インターフェース (API) の概念のほか、その利点や機能について説明します。
重要: Caching Proxy は、すべての Edge コンポーネントのインストールで使用可能です。ただし、次の例外があります。
この API は、Caching Proxy へのインターフェースであり、プロキシー・サーバーの基本機能を拡張することができます。拡張機能またはプラグインを作成し、次の例を含むカスタマイズされた処理を実行できます。
Caching Proxy API には、次のような利点があります。
Caching Proxy プラグイン・プログラムを作成するには、あらかじめプロキシー・サーバーの機能を理解しておく必要があります。プロキシー・サーバーの振る舞いは、いくつかの別個の処理ステップに分けることができます。これらのそれぞれのステップで、API を使用して独自にカスタマイズした機能を使用することが可能です。例えば、ある処理をクライアント要求の読み取り後、他の処理を行う前に行う、あるいは特殊ルーチンを認証時に実行してから、要求ファイルの送信後に再度行うなどを決めます。
事前定義機能のライブラリーには API が備わっています。ご使用のプラグイン・プログラムは、プロキシー・サーバー・プロセス (例えば、要求の操作、要求ヘッダーの読み取りまたは書き込み、あるいはプロキシー・サーバーのログへの書き込みなど) と対話するために事前定義 API 関数を呼び出すことができます。これらの関数を、自分で作成したプラグイン関数と混同しないでください。プラグイン関数は、プロキシー・サーバーによって呼び出されます。事前定義関数については、事前定義関数およびマクロで説明しています。
サーバー構成ファイル内の対応する Caching Proxy API ディレクティブを使用して、適切なステップでプラグイン関数を呼び出すように、プロキシー・サーバーに指示します。これらのディレクティブについては、API ステップの Caching Proxy 構成ディレクティブで説明しています。
本書には、次の内容が含まれています。
以下のコンポーネントとプロシージャーを使用して独自の Caching Proxy プラグイン・プログラムを作成することができます。
プロキシー・サーバーの基本操作は、そのフェーズでサーバーが実行する処理のタイプに基づいていくつかのステップに分けることができます。各ステップには、プログラムの指定された部分を実行できる接続点があります。Caching Proxy 構成ファイル (ibmproxy.conf) に API ディレクティブを追加することによって、特定のステップで呼び出すプラグイン関数を指定します。そのステップに複数のディレクティブを組み込むことによって、特定のプロセス・ステップで複数のプラグイン関数を呼び出すことができます。
いくつかのステップはサーバー要求プロセスの一部です。言い換えると、プロキシー・サーバーは、要求を処理するたびにこれらのステップを実行します。その他のステップは要求処理とは無関係に実行されます。つまり、要求が処理されているかどうかにかかわらず、サーバーはこれらのステップを実行します。
コンパイルされたプログラムは、オペレーティング・システムに応じて、いずれかの共用オブジェクト (例えば、DLL または .so ファイル) に入っています。サーバーは、その要求プロセス・ステップを進めながら、いずれかの関数が要求の処理を終えたことを示すまでは、各ステップに関連付けられたプラグイン関数を呼び出します。特定のステップのプラグイン関数が複数ある場合は、これらの関数は構成ファイル内にあるディレクティブの順序で呼び出されます。
要求がプラグイン関数によって処理されない (そのステップに Caching Proxy API ディレクティブを組み込まなかったか、そのステップのプラグイン関数が HTTP_NOACTION を戻した) 場合には、サーバーはそのステップのデフォルト・アクションを実行します。
注 : これは、Service ステップを除くすべてのステップにあてはまります。Service ステップにはデフォルト・アクションはありません。
図 1 は、プロキシー・サーバー・プロセスのステップを表し、要求処理に関連するステップの処理順序を定義しています。
この図の中の 4 つのステップは、クライアント要求の処理とは無関係に実行されます。これらのステップは、プロキシー・サーバーの実行および保守に関連します。これらのステップには以下が含まれます。
以下のリストは、図 1 に示した各ステップの目的を示しています。すべてのステップが特定の要求に対して呼び出されるわけではないことに注意してください。
要求が読み込まれた後、まだ何も実行されないうちに処理を実行します。
このステップで要求が処理されたことを示す標識 (HTTP_OK) が戻された場合には、サーバーは要求プロセスの他のステップをバイパスし、Transmogrifier、Log、および PostExit ステップだけを実行します。
保管されたセキュリティー・トークンを使用して保護、ACL、およびその他のアクセス制御用の物理パスを検査し、基本認証に必要な WWW 認証ヘッダーを生成します。独自のプラグイン関数を作成してこのステップを置き換える場合は、これらのヘッダーを自分で生成しなければなりません。
詳細については、認証および許可を参照してください。
セキュリティー・トークンのデコード、検査、および保管を行います。
詳細については、認証および許可を参照してください。
許可およびオブジェクト検索後に (ただし要求が満たされる前に) 処理を実行します。
このステップで要求が処理されたことを示す標識 (HTTP_OK) が戻された場合には、サーバーは要求プロセスの他のステップをバイパスし、Transmogrifier、Log、および PostExit ステップだけを実行します。
AIX(R) システムでは、プラグイン関数をリストするエクスポート・ファイル (例えば libmyapp.exp) が必要であり、 Caching Proxy API インポート・ファイル (libhttpdapi.exp) とリンクする必要があります。
Linux、HP-UX、および Solaris システムでは、libhttpdapi および libc ライブラリーとリンクする必要があります。
Windows(R) システムでは、プラグイン関数をリストするモジュール定義ファイル (.def) が必要であり、 HTTPDAPI.LIB とリンクする必要があります。
関数定義に HTAPI.h を組み込み、HTTPD_LINKAGE マクロを使用します。このマクロを使用すると、すべての関数で必ず同じ呼び出し規則を使用できます。
以下のコンパイル・コマンドおよびリンク・コマンドを、ガイドラインとして使用します。
cc_r -c -qdbxextra -qcpluscmt foo.c
cc_r -bM:SRE -bnoentry -o libfoo.so foo.o -bI:libhttpdapi.exp -bE:foo.exp
(このコマンドは、読みやすくするために 2 行にわたって示されています。)
cc -Ae -c +Z +DAportable
aCC +Z -mt -c +DAportable
gcc -c foo.c
ld -G -Bsymbolic -o libfoo.so foo.o -lhttpdapi -lc
cc -mt -Bsymbolic -c foo.c
cc -mt -Bsymbolic -G -o libfoo.so foo.o -lhttpdapi -lc
cl /c /MD /DWIN32 foo.c
link httpdapi.lib foo.obj /def:foo.def /out:foo.dll /dll
エクスポートを指定するには、以下のいずれかの方法を使用します。
定義済み要求処理ステップ用の独自のプログラム関数を作成する場合は、プラグイン関数プロトタイプに示した構文に従ってください。
各ユーザー関数では、実行されたアクションを示す値が戻りコード・パラメーターに使用される必要があります。
Caching Proxy ステップごとの関数プロトタイプは、使用する形式を示し、それらが実行できる処理のタイプを示します。関数名は事前定義されないので、注意してください。関数には固有の名前を指定する必要がありますが、命名規則は自由に決めることができます。わかりやすくするため、本書では、サーバーの処理ステップに関連する名前を使用しています。
各プラグイン関数で、特定の事前定義 API 関数が有効です。すべてのステップで無効な事前定義関数もあります。以下の事前定義 API 関数は、これらのどのプラグイン関数からでも呼び出すことができます。
その他の有効または無効な API 関数については、関数のプロトタイプの説明に示されています。
関数に送られる handle パラメーターの値は、最初の引数として事前定義関数に渡すことができます。事前定義 API 関数については、事前定義関数およびマクロで説明しています。
void HTTPD_LINKAGE ServerInitFunction ( unsigned char *handle, unsigned long *major_version, unsigned long *minor_version, long *return_code )
このステップに定義された関数は、サーバー初期化の間のモジュールのロード時に一度呼び出されます。初期化を行うことができるのはいずれかの要求が受け入れられる前です。
すべてのサーバー初期化関数が呼び出されますが、このステップの関数からエラー戻りコードが戻されると、サーバーはエラー・コードを戻した関数と同じモジュールで構成された他のすべての関数を無視します。 (つまり、エラーを戻した関数と同じ共用オブジェクトに入っている関数はどれも呼び出されません。)
バージョン・パラメーターにはプロキシー・サーバーのバージョン番号が含まれます。バージョン・パラメーターは Caching Proxy によって指定されます。
void HTTPD_LINKAGE PreExitFunction ( unsigned char *handle, long *return_code )
このステップに定義された関数は、要求が読み取られた後、処理が行われる前にそれぞれの要求ごとに呼び出されます。このステップのプラグインを使用することにより、クライアントの要求が Caching Proxy によって処理される前に、この要求にアクセスできます。
preExit 関数の有効な戻りコードは次のとおりです。
その他の戻りコードは使用しないでください。
この関数が HTTP_OK を戻した場合、プロキシー・サーバーは、要求が処理されたものと想定します。それ以降のすべての要求処理ステップはバイパスされ、応答ステップ (Transmogrifier、 Log、および PostExit) のみが実行されます。
このステップ中は、事前定義 API 関数はすべて有効です。
void HTTPD_LINKAGE MidnightFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は毎日、真夜中に実行されます。要求コンテキストは含まれていません。例えば、この関数はログを分析する子プロセスを起動するために使用できます。 (このステップで処理が長引くと、ロギングの妨げになる可能性があることに注意してください。)
void HTTPD_LINKAGE AuthenticationFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求の認証方式に基づいて要求ごとに呼び出されます。この関数は、要求とともに送信されるセキュリティー・トークンの検査をカスタマイズするために使用できます。
void HTTPD_LINKAGE NameTransFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求ごとに呼び出されます。テンプレートと一致する要求のみについてプラグイン関数が呼び出されるようにしたい場合は、 URL テンプレートを構成ファイル・ディレクティブに指定します。 Name Translation ステップは要求が処理される前に実行され、URL をファイル名などのオブジェクトにマッピングするためのメカニズムを提供します。
void HTTPD_LINKAGE AuthorizationFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求ごとに呼び出されます。テンプレートと一致する要求のみについてプラグイン関数が呼び出されるようにしたい場合は、 URL テンプレートを構成ファイル・ディレクティブに指定します。 Authorization ステップは要求が処理される前に実行され、識別されたオブジェクトをクライアントに戻すことができるかどうかを検査するために使用できます。基本認証を行う場合は、必要な WWW 認証ヘッダーを生成しなければなりません。
void HTTPD_LINKAGE ObjTypeFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求ごとに呼び出されます。テンプレートと一致する要求のみについてプラグイン関数が呼び出されるようにしたい場合は、 URL テンプレートを構成ファイル・ディレクティブに指定します。 Object Type ステップは要求が処理される前に実行され、オブジェクトが存在するかどうかを調べてオブジェクトの型定義を行うために使用できます。
void HTTPD_LINKAGE PostAuthFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求を許可してから処理が起こるまえに呼び出されます。この関数が HTTP_OK を戻した場合、プロキシー・サーバーは、要求が処理されたものと想定します。それ以降のすべての要求ステップはバイパスされ、応答ステップ (Transmogrifier、 Log、および PostExit) のみが実行されます。
このステップ中は、サーバー事前定義関数はすべて有効です。
void HTTPD_LINKAGE ServiceFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求ごとに呼び出されます。テンプレートと一致する要求のみについてプラグイン関数が呼び出されるようにしたい場合は、 URL テンプレートを構成ファイル・ディレクティブに指定します。 Service ステップは、要求が PreExit または PostAuthorization ステップで満たされなかった場合に、この要求を満たします。
このステップ中は、サーバー事前定義関数はすべて有効です。
URL ではなく HTTP メソッドに基づいて実行する Service 関数の構成については、「WebSphere Application Server Caching Proxy 管理ガイド」の Enable ディレクティブの項を参照してください。
このステップには、以下の 4 つの関数をインプリメントしなければなりません。 (使用する関数名は、以下で使用されているものと同じでなくてもかまいません。)
void * HTTPD_LINKAGE openFunction ( unsigned char *handle, long *return_code )
open 関数は、このストリームのデータの処理に必要な初期化 (バッファー割り振りなど) を実行します。 HTTP_OK 以外の戻りコードが戻されると、このフィルターは打ち切りになります (write 関数も close 関数も呼び出されません)。関数は void ポインターを戻すことができるので、構造にスペースを割り振り、後続の関数の correlator パラメーターで戻されるポインターをもつことができます。
void HTTPD_LINKAGE writeFunction ( unsigned char *handle, unsigned char *data, /* response data sent by the origin server */ unsigned long *length, /* length of response data */ void *correlator, /* pointer returned by the 'open' function */ long *return_code )
write 関数はデータを処理し、新規または変更データを指定してサーバーの事前定義 HTTPD_write() 関数を呼び出すことができます。プラグイン側では、渡されたバッファーを解放しないでください。また、サーバーが受け取ったバッファーを解放することもありません。
write 関数の有効範囲でデータを変更しないようにする場合は、open、 write、または close 関数の有効範囲で HTTPD_write() 関数を呼び出して、クライアントへの応答に対してデータを渡す必要があります。 correlator 引数はデータ・バッファーを指すポインターで、open ルーチンで戻されたものです。
void HTTPD_LINKAGE closeFunction ( unsigned char *handle, void *correlator, long *return_code )
close 関数は、このストリームのデータの処理を完了するために必要なクリーンアップ・アクション (correlator バッファーのフラッシュや解放など) を行います。 correlator 引数はデータ・バッファーを指すポインターで、open ルーチンで戻されたものです。
void HTTPD_LINKAGE errorFunction ( unsigned char *handle, void *correlator, long *return_code )
error 関数により、エラー・ページが送信される前に、バッファー内にあるデータのフラッシュまたは解放 (あるいはその両方) などのクリーンアップ・アクションを行うことができるようになります。この時点で、エラー・ページを処理するために open、write、および close 関数が呼び出されます。correlator 引数はデータ・バッファーを指すポインターで、open ルーチンで戻されたものです。
注:
void HTTPD_LINKAGE GCAdvisorFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、ガーベッジ・コレクションの際、キャッシュ内のファイルごとに呼び出されます。この関数によって、保持するファイルと廃棄するファイルの決定に影響を与えることができます。詳細については、GC_* 変数を参照してください。
void HTTPD_LINKAGE ProxyAdvisorFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、各プロキシー要求のサービス時に呼び出されます。例えば、USE_PROXY 変数を設定するために使用することができます。
void HTTPD_LINKAGE LogFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求が処理され、クライアントへの通信がクローズされた後で、それぞれの要求ごとに呼び出されます。テンプレートと一致する要求のみについてプラグイン関数が呼び出されるようにしたい場合は、 URL テンプレートを構成ファイル・ディレクティブに指定します。この関数は、要求処理の成否に関係なく呼び出されます。ログ・プラグインにデフォルトのログ・メカニズムを変更させたくない場合は、戻りコードを HTTP_OK ではなく HTTP_NOACTION に設定します。
void HTTPD_LINKAGE ErrorFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、失敗した要求ごとに呼び出されます。テンプレートと一致する、失敗した要求のみについてプラグイン関数が呼び出されるようにしたい場合は、 URL テンプレートを構成ファイル・ディレクティブに指定します。 Error ステップを使用して、エラー応答をカスタマイズできます。
void HTTPD_LINKAGE PostExitFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、要求の成否に関係なく、要求ごとに呼び出されます。このステップを使用して、要求を処理するプラグインによって割り振られたリソースに対してクリーンアップ・タスクを行うことができます。
void HTTPD_LINKAGE ServerTermFunction ( unsigned char *handle, long *return_code )
このステップで定義された関数は、サーバーが正常にシャットダウンしたときに呼び出されます。これにより、サーバー初期化ステップの際に割り振られたリソースをクリーンアップすることができます。このステップでは、いずれの HTTP_* 関数も呼び出さないでください (呼び出しの結果は保証できません)。構成ファイルに Server Termination 用の複数の Caching Proxy API ディレクティブがある場合は、それらがすべて呼び出されます。
これらの戻りコードは、World Wide Web Consortium によって公開されている HTTP 1.1 仕様書 (www.w3.org/pub/WWW/Protocols/) の RFC 2616 に準拠しています。プラグイン関数は、以下のいずれかの値を戻す必要があります。
値 | 戻りコード |
0 | HTTP_NOACTION |
100 | HTTP_CONTINUE |
101 | HTTP_SWITCHING_PROTOCOLS |
200 | HTTP_OK |
201 | HTTP_CREATED |
202 | HTTP_ACCEPTED |
203 | HTTP_NON_AUTHORITATIVE |
204 | HTTP_NO_CONTENT |
205 | HTTP_RESET_CONTENT |
206 | HTTP_PARTIAL_CONTENT |
300 | HTTP_MULTIPLE_CHOICES |
301 | HTTP_MOVED_PERMANENTLY |
302 | HTTP_MOVED_TEMPORARILY |
302 | HTTP_FOUND |
303 | HTTP_SEE_OTHER |
304 | HTTP_NOT_MODIFIED |
305 | HTTP_USE_PROXY |
307 | HTTP_TEMPORARY_REDIRECT |
400 | HTTP_BAD_REQUEST |
401 | HTTP_UNAUTHORIZED |
403 | HTTP_FORBIDDEN |
404 | HTTP_NOT_FOUND |
405 | HTTP_METHOD_NOT_ALLOWED |
406 | HTTP_NOT_ACCEPTABLE |
407 | HTTP_PROXY_UNAUTHORIZED |
408 | HTTP_REQUEST_TIMEOUT |
409 | HTTP_CONFLICT |
410 | HTTP_GONE |
411 | HTTP_LENGTH_REQUIRED |
412 | HTTP_PRECONDITION_FAILED |
413 | HTTP_ENTITY_TOO_LARGE |
414 | HTTP_URI_TOO_LONG |
415 | HTTP_BAD_MEDIA_TYPE |
416 | HTTP_BAD_RANGE |
417 | HTTP_EXPECTATION_FAILED |
500 | HTTP_SERVER_ERROR |
501 | HTTP_NOT_IMPLEMENTED |
502 | HTTP_BAD_GATEWAY |
503 | HTTP_SERVICE_UNAVAILABLE |
504 | HTTP_GATEWAY_TIMEOUT |
505 | HTTP_BAD_VERSION |
ユーザー独自のプラグイン関数から、サーバーの事前定義関数とマクロを呼び出すことができます。その事前定義された名前を使用し、以下の形式に従う必要があります。パラメーターの説明で、 i は入力パラメーターを示し、o は出力パラメーターを示し、 i/o はパラメーターが入力と出力の両方であることを示しています。
これらの関数は、要求の結果に応じて、いずれかの HTTPD 戻りコードを戻します。これらのコードについては、事前定義関数およびマクロからの戻りコードで説明しています。
これらの関数を呼び出すときは、プラグインへ提供されたハンドルを最初のパラメーターとして使用します。最初のパラメーターとして使用しない場合、関数は HTTPD_PARAMETER_ERROR エラー・コードを戻します。 NULL は、有効なハンドルとしては受け入れられません。
void HTTPD_LINKAGE HTTPD_authenticate ( unsigned char *handle, /* i; handle */ long *return_code /* o; return code */ )
void HTTPD_LINKAGE HTTPD_cacheable_url ( unsigned char *handle, /* i; handle */ unsigned char *url, /* i; URL to check */ unsigned char *req_method, /* i; request method for the URL */ long *retval /* o; return code */ )
戻り値 HTTPD_SUCCESS は、URL コンテンツがキャッシュできることを示します。HTTPD_FAILURE はコンテンツがキャッシュできないことを示します。また、HTTPD_INTERNAL_ERROR もこの関数の可能な戻りコードです。
void HTTPD_LINKAGE HTTPD_close ( unsigned char *handle, /* i; handle */ long *return_code /* o; return code */ )
void HTTPD_LINKAGE HTTPD_exec ( unsigned char *handle, /* i; handle */ unsigned char *name, /* i; name of script to run */ unsigned long *name_length, /* i; length of the name */ long *return_code /* o; return code */ )
void HTTPD_LINKAGE HTTPD_extract ( unsigned char *handle, /* i; handle */ unsigned char *name, /* i; name of variable to extract */ unsigned long *name_length, /* i; length of the name */ unsigned char *value, /* o; buffer in which to put the value */ unsigned long *value_length, /* i/o; buffer size */ long *return_code /* o; return code */ )
この関数が HTTPD_BUFFER_TOO_SMALL コードを戻した場合、要求したバッファー・サイズは、抽出された値を入れるのに十分な大きさではありませんでした。この場合、この関数はバッファーを使用せず、この値を正常に抽出するために必要なバッファー・サイズで value_length パラメーターを更新します。少なくとも、戻された value_length と同じ大きさのバッファーを使用して抽出を再試行します。
void HTTPD_LINKAGE HTTPD_file ( unsigned char *handle, /* i; handle */ unsigned char *name, /* i; name of file to send */ unsigned long *name_length, /* i; length of the name */ long *return_code /* o; return code */ )
const unsigned char * /* o; value of variable */ HTTPD_LINKAGE httpd_getvar( unsigned char *handle, /* i; handle */ unsigned char *name, /* i; variable name */ unsigned long *n /* i; index number for the array containing the header */ )
ヘッダーが入っている配列の指標は 0 から始まります。配列で最初の項目を得るには、n に値 0 を使用します。5 番目の項目を得るには、n には値 4 を使用します。
void HTTPD_LINKAGE HTTPD_log_access ( unsigned char *handle, /* i; handle */ unsigned char *value, /* i; data to write */ unsigned long *value_length, /* i; length of the data */ long *return_code /* o; return code */ )
サーバー・アクセス・ログにパーセント記号 (%) を書き込むときに、エスケープ記号は必要がない ことに注意してください。
void HTTPD_LINKAGE HTTPD_log_error ( unsigned char *handle, /* i; handle */ unsigned char *value, /* i; data to write */ unsigned long *value_length, /* i; length of the data */ long *return_code /* o; return code */ )
サーバー・エラー・ログにパーセント記号 (%) を書き込むときに、エスケープ記号は必要がない ことに注意してください。
void HTTPD_LINKAGE HTTPD_log_event ( unsigned char *handle, /* i; handle */ unsigned char *value, /* i; data to write */ unsigned long *value_length, /* i; length of the data */ long *return_code /* o; return code */ )
サーバー・イベント・ログにパーセント記号 (%) を書き込むときに、エスケープ記号は必要がない ことに注意してください。
void HTTPD_LINKAGE HTTPD_log_trace ( unsigned char *handle, /* i; handle */ unsigned char *value, /* i; data to write */ unsigned long *value_length, /* i; length of the data */ long *return_code /* o; return code */ )
サーバー・トレース・ログにパーセント記号 (%) を書き込むときに、エスケープ記号は必要がない ことに注意してください。
void HTTPD_LINKAGE HTTPD_open ( unsigned char *handle, /* i; handle */ long *return_code /* o; return code */ )
void HTTPD_LINKAGE HTTPD_proxy ( unsigned char *handle, /* i; handle */ unsigned char *url_name, /* i; URL for the proxy request */ unsigned long *name_length, /* i; length of URL */ void *request_body, /* i; body of request */ unsigned long *body_length, /* i; length of body */ long *return_code /* o; return code */ )
void HTTPD_LINKAGE HTTPD_read ( unsigned char *handle, /* i; handle */ unsigned char *value, /* i; buffer for data */ unsigned long *value_length, /* i/o; buffer size (data length) */ long *return_code /* o; return code */ )
void HTTPD_LINKAGE HTTPD_restart ( long *return_code /* o; return code */ )
この関数で変数を作成することもできますので注意してください。作成する変数は、 変数で説明されている、接頭部 HTTP_ および PROXY_ の規則に準拠します。 HTTP_ で始まる変数を作成した場合、この変数は、接頭部 HTTP_ なしで、クライアントへの応答でヘッダーとして送信されます。例えば、Location ヘッダーを設定するには、変数名 HTTP_LOCATION で HTTPD_set() を使用します。接頭部 PROXY_ を付けて作成した変数は、コンテンツ・サーバーへの要求でヘッダーとして送信されます。接頭部 CGI_ を付けて作成した変数は CGI プログラムに渡されます。
この関数はすべてのステップで有効です。ただし、すべての変数がすべてのステップで有効であるとは限りません。
void HTTPD_LINKAGE HTTPD_set ( unsigned char *handle, /* i; handle */ unsigned char *name, /* i; name of value to set */ unsigned long *name_length, /* i; length of the name */ unsigned char *value, /* i; buffer with value */ unsigned long *value_length, /* i; length of value */ long *return_code /* o; return code */ )
long /* o; return code */ HTTPD_LINKAGE httpd_setvar ( unsigned char *handle, /* i; handle */ unsigned char *name, /* i; variable name */ unsigned char *value, /* i; new value */ unsigned long *addHdr /* i; add header or replace it */ )addHdr
パラメーターには、以下の 4 つの値を使用できます。
これらの値は HTAPI.h で定義されます。
void HTTPD_LINKAGE httpd_variant_insert ( unsigned char *handle, /* i; handle */ unsigned char *URI, /* i; URI of this object */ unsigned char *dimension, /* i; dimension of variation */ unsigned char *variant, /* i; value of the variant */ unsigned char *filename, /* i; file containing the object */ long *return_code /* o; return code */ )
注:
Mozilla 4.0 (compatible; BatBrowser 94.1.2; Bat OS)
void HTTPD_LINKAGE httpd_variant_lookup ( unsigned char *handle, /* i; handle */ unsigned char *URI, /* URI of this object */ unsigned char *dimension, /* i; dimension of variation */ unsigned char *variant, /* i; value of the variant */ long *return_code); /* o; return code */
初めてこの関数を呼び出す前にコンテンツ・タイプを設定しなかった場合、サーバーは、CGI データ・ストリームが送信されるものと想定します。
void HTTPD_LINKAGE HTTPD_write ( unsigned char *handle, /* i; handle */ unsigned char *value, /* i; data to send */ unsigned char *value_length, /* i; length of the data */ long *return_code); /* o; return code */
サーバーは、要求の結果に応じて、以下のいずれかの値に戻りコード・パラメーターを設定します。
値 | 状況コード | 説明 |
---|---|---|
-1 | HTTPD_UNSUPPORTED | この関数はサポートされていません。 |
0 | HTTPD_SUCCESS | この関数は正常に実行され、出力フィールドが有効です。 |
1 | HTTPD_FAILURE | 関数は失敗しました。 |
2 | HTTPD_INTERNAL_ERROR | 内部エラーを検出し、この要求の処理を続行できません。 |
3 | HTTPD_PARAMETER_ERROR | 1 つまたは複数の無効なパラメーターが渡されました。 |
4 | HTTPD_STATE_CHECK | この関数はこのプロセス・ステップでは無効です。 |
5 | HTTPD_READ_ONLY | (これを戻すのは HTTPD_set と httpd_setvar だけです。) 変数は読み取り専用であり、プラグインによって設定できません。 |
6 | HTTPD_BUFFER_TOO_SMALL | (これを戻すのは HTTPD_set、 httpd_setvar、および HTTPD_read だけです。)指定のバッファーが小さすぎます。 |
7 | HTTPD_AUTHENTICATE_FAILED | (これを戻すのは HTTPD_authenticate だけです。) 認証は失敗しました。詳細については、HTTP_RESPONSE および HTTP_REASON 変数を調べてください。 |
8 | HTTPD_EOF | (これを戻すのは HTTPD_read だけです。) 要求本文の終わりを示します。 |
9 | HTTPD_ABORT_REQUEST | クライアントが要求が指定する条件と一致しないエンティティー・タグを指定したために、要求は打ち切られました。 |
10 | HTTPD_REQUEST_SERVICED | (これを戻すのは HTTPD_proxy だけです。) 呼び出した関数はこの要求の応答を完了しました。 |
11 | HTTPD_RESPONSE_ALREADY_COMPLETED | その要求の応答はすでに完了しているので、この関数は失敗しました。 |
12 | HTTPD_WRITE_ONLY | 変数は書き込み専用であり、プラグインによって読み取ることはできません。 |
要求プロセスの各ステップには構成ディレクティブがあり、これを使用して、そのステップの間に呼び出して実行したいプラグイン関数を示すことができます。サーバーの構成ファイル (ibmproxy.conf) にそれらのディレクティブを追加するには、サーバーの構成ファイルを手操作で編集して更新するか、または Caching Proxy の「構成および管理」フォームの中の 「API 要求処理」フォームを使用します。
つまり、サーバーは、Service、NameTrans、Exec、Fail、Map、Pass、Proxy、 ProxyWAS、および Redirect の各ディレクティブを構成ファイル内に並んでいる順序で処理します。サーバーが URL をファイルに正常にマップすると、サーバーはこれらのディレクティブ以外のディレクティブを読み取ったり、処理したりしません。 (Map ディレクティブは例外です。プロキシー・サーバーのマッピング・ルールについて詳しくは、「WebSphere Application Server Caching Proxy 管理ガイド」を参照してください。)
これらの構成ファイル・ディレクティブは、ここに明確に指定されたものを除いてスペースを入れずに、ibmproxy.conf ファイル中に 1 行で記述しなければなりません。構文例の一部では読みやすさのために改行していますが、実際のディレクティブではそこにスペースを入れないでください。
これらのディレクティブの変数には、以下の意味があります。
パス情報にアクセスする場合、Service ディレクティブには、関数名の後にアスタリスク (*) が必要です。
これらのディレクティブの構文など、詳細については、「WebSphere Application Server Caching Proxy 管理ガイド」を参照してください。
Caching Proxy API は、バージョン 4.6.1 まで ICAPI および GWAPI と下位互換性があります。
Caching Proxy API を使用するために C で作成された CGI アプリケーションを移植する場合、以下のガイドラインを使用します。
API プログラムの作成に際しては、リモート・クライアントおよびサーバー・システムに関する情報を提供する Caching Proxy 変数を使用することができます。
注 :
ACCEPT_RANGES BYTES CLIENT_ADDR 9.67.84.3
この変数は、PostAuthorization、PostExit、ProxyAdvisor、または Log ステップで使用できます。
http://www.anynet.com/~userk/main.htm
Mon, 01 Mar 2002 19:41:17 GMT
Mon, 01 Mar 1998 19:41:17 GMT
d:¥wwwhome¥foo
/wwwhome/foo
application/x-www-form-urlencoded
7034
NAME=Eugene+T%2E+Fox&ADDR=etfox%7Cibm.net&INTEREST=xyz
http://www.company.com/homepage
application/x-www-form-urlencoded
まず、用語を簡単に説明します。
図 3 は、プロキシー・サーバーによる認証および許可のプロセスを表しています。
図 3 に示したように、サーバーによる許可と認証のプロセスの最初のステップは、許可プロセスの開始です。
Caching Proxy において、認証は許可プロセスの一部で、これが発生するのは、許可が必要な場合に限られます。
プロキシー・サーバーは、許可を必要とする要求を処理するとき以下のステップに従います。
Caching Proxy プラグインが独自の許可プロセスを備えている場合、そのプロセスがデフォルトのサーバーの許可および認証を上書き します。したがって、構成ファイルに許可ディレクティブがある場合には、それらに関連するプラグイン関数は、必要な認証を処理する必要もあります。これに使用するために、事前定義 HTTPD_authenticate() 関数が用意されています。
許可プラグインに認証を備えるには、次の 3 つの方法があります。
Authorization ステップを実行すると、それが許可プラグイン関数を実行し、次にその許可が認証プラグイン関数を呼び出します。
Authorization ステップを実行すると、それが許可プラグイン関数を実行し、次にその許可がデフォルト・サーバー認証を呼び出します。
Authorization ステップを実行すると、それが許可プラグイン関数と、その許可プラグイン関数に含まれる認証を実行します。
Caching Proxy プラグインが独自の許可プロセスを備えていない場合でも、次の方法を使用して、カスタマイズされた認証を提供することができます。
Authorization ステップを実行すると、それがデフォルトのサーバー許可を実行し、次にその許可が認証プラグイン関数を呼び出します。
以下の点に注意してください。
元の文書 (URI) が変更されたデータをキャッシュする場合は、バリアント・キャッシュを使用します。Caching Proxy は、API によって生成されたバリアントを処理します。バリアントとは、基本文書の別バージョンです。
一般に、起点サーバーはバリアントを送信するときに、それらがバリアントであることを識別できません。Caching Proxy は、プラグインによって作成されたバリアント (例えばコード・ページ変換) だけをサポートします。プラグインが HTTP ヘッダーに入っていない基準に基づいてバリアントを作成する場合は、プラグインに PreExit または PostAuthorization ステップ関数を組み込んで疑似ヘッダーを作成して、 Caching Proxy が既存のバリアントを正しく識別できるようにしなければなりません。
例えば、ブラウザーが送信する User-Agent ヘッダーの値に基づいてユーザーが要求したデータを変更するには、Transmogrifier API プログラムを使用します。 close 関数で、変更された内容をファイルに保管するか、またはバッファー長を指定してデータ引数としてバッファーを渡します。その後で、バリアント・キャッシュ関数 httpd_variant_insert() および httpd_variant_lookup() を使用して、コンテンツをキャッシュに入れます。
Edge Components インストール CD-ROM の samples ディレクトリーに提供されているサンプル・プログラムを参照して、独自の Caching Proxy API 関数の作成に役立ててください。 WebSphere Application Server Web サイト www.ibm.com/software/webservers/appserv/ に追加情報があります。
このセクションでは、Load Balancer 用のカスタム・アドバイザーの作成について説明します。
アドバイザーは、指定サーバー上のロードに関する情報を提供するために Load Balancer 内部で働くソフトウェア・エージェントです。各標準プロトコル (HTTP、SSL、その他) ごとに異なるアドバイザーが存在します。定期的に、 Load Balancer 基本コードがアドバイザー・サイクルを実行します。このサイクルで、構成内のすべてのサーバーの状況が個別に評価されます。
Load Balancer 用の独自のアドバイザーを作成することによって、サーバー・マシンのロードを判別する方法をカスタマイズできます。
Windows システム: Load Balancer (IPv4 および IPv6 用) インストール済み環境で IPv6 プロトコルを使用する際、アドバイザーを使用するには、 C:¥windows¥system32¥drivers¥etc¥ ディレクトリーにある プロトコル・ファイルを修正する必要があります。
IPv6 の場合、プロトコル・ファイルに次の行を挿入します。
ipv6-icmp 58 IPv6-ICMP # IPv6 interface control message protocol
一般に、アドバイザーは、以下のようにロード・バランシングを可能にするために働きます。
Load Balancer に提供されている標準アドバイザーには、以下の機能のためのアドバイザーが含まれます。これらのアドバイザーに関する詳細情報は「WebSphere Application Server Load Balancer 管理ガイド」に記載されています。
標準アドバイザーが提供されていない所有プロトコルをサポートするには、カスタム・アドバイザーを作成しなければなりません。
カスタム・アドバイザーはクラス・ファイルとして提供される小さい Java コードであり、これはサーバー上のロードを判別するために Load Balancer 基本コードによって呼び出されます。基本コードは、カスタム・アドバイザーのインスタンスの開始と停止、状況および報告書の提供、ヒストリー情報のログ・ファイルへの記録、さらにアドバイザー結果のマネージャー・コンポーネントへの報告など、必要なすべての管理サービスを提供します。
Load Balancer 基本コードがカスタム・アドバイザーを呼び出すと、以下のステップが実行されます。
カスタム・アドバイザーは、Load Balancer と通常モードまたは置換モードで対話するよう設計することができます。
操作モードの選択は、カスタム・アドバイザー・ファイルで、コンストラクター・メソッドのパラメーターとして指定されます。(各アドバイザーは設計に基づいて、上記のモードのいずれかでのみ稼動します。)
通常モードでは、カスタム・アドバイザーがサーバーとデータを交換し、基本アドバイザー・コードが交換の時間を測定して、ロード値を計算します。その後、基本コードがこのロード値をマネージャーに報告します。成功を示す場合は値ゼロが、またはエラーを示す場合は -1 がカスタム・アドバイザーから戻されます。
通常モードを指定するには、コンストラクター内の replace フラグを false に設定してください。
置換モードでは、基本コードはいかなる時間測定も行いません。カスタム・アドバイザーはその固有の要件に基づいて、指定された操作をすべて実行し、その後、実際のロード値を戻します。基本コードはそのロード値を受け入れ、それをそのままマネージャーに報告します。最良の結果を得るには、高速サーバーを表す 10 と低速サーバーを表す 1000 によって、ロード値を 10 から 1000 の間で正規化してください。
置換モードを指定するには、コンストラクター内の replace フラグを true に設定してください。
カスタム・アドバイザー・ファイル名は ADV_name.java という形式に従わなければなりません。ここで name はアドバイザーのために選択する名前です。完全な名前は大文字の接頭部 ADV_ で始まり、後続の文字がすべての小文字でなければなりません。ここで小文字を使用することにより、アドバイザーを実行するためのコマンドでの大/小文字の区別が不要になります。
Java の規則に従って、ファイル内で定義されるクラスの名前はファイルの名前と一致しなければなりません。
カスタム・アドバイザーは Java 言語で作成し、そのコンパイルには、開発マシンにインストールされている Java コンパイラーを使用する必要があります。コンパイル時には、以下のファイルが参照されます。
コンパイル時には、クラスパス環境変数がカスタム・アドバイザー・ファイルと基本クラス・ファイルの両方を指していなければなりません。コンパイル・コマンドの形式は次のようになります。
javac -classpath /opt/ibm/edge/lb/servers/lib/ibmnd.jar ADV_name.java
この例では、デフォルトの Linux および UNIX インストール・パスが使用されています。アドバイザー・ファイルの名前が ADV_name.java で、アドバイザー・ファイルは現行ディレクトリーに保管されます。
コンパイルの出力は ADV_name.class などのクラス・ファイルです。アドバイザーを開始する前に、クラス・ファイルを install_path/servers/lib/CustomAdvisors/ ディレクトリーにコピーしてください。
カスタム・アドバイザーを実行するには、最初にアドバイザーのクラス・ファイルを Load Balancer マシン上の lib/CustomAdvisors サブディレクトリーにコピーする必要があります。例えば、myping というカスタム・アドバイザーの場合、ファイル・パスは、install_path/servers/lib/CustomAdvisors/ADV_myping.class になります。
Load Balancer を構成し、そのマネージャー機能を開始し、カスタム・アドバイザーを開始するコマンドを発行します。カスタム・アドバイザーは、次のように、その名前から ADV_ 接頭部とファイル拡張子を除いたものによって指定されます。
dscontrol advisor start myping port_number
コマンドに指定するポート番号は、アドバイザーがターゲット・サーバーとの接続をオープンするポートです。
すべてのアドバイザーと同様に、カスタム・アドバイザーは、ADV_Base と呼ばれるアドバイザー基本クラスの機能性を拡張します。アドバイザー・ベースは、マネージャーの重みアルゴリズムで使用するためにロードをマネージャーに報告するなど、アドバイザーの関数の大部分を実行します。アドバイザー・ベースはまた、ソケット接続およびクローズ操作を実行し、アドバイザーが使用する送信および受信メソッドを提供します。アドバイザーは、調査中のサーバー用に指定されたポートでデータを送信および受信するためだけに使用されます。アドバイザー・ベース内の TCP メソッドは、ロードを計算するために時間測定されます。アドバイザー・ベースのコンストラクター内のフラグが、既存のロードをアドバイザーから戻された新しいロードで上書きするかどうかを示します。
アドバイザーには、以下の基本クラス・メソッドがあります。
これらの必須ルーチンに関する詳細は、このセクションで後述します。
カスタム・アドバイザーは、ネイティブ・アドバイザーまたは標準アドバイザーを検索した後に呼び出されます。 Load Balancer が指定のアドバイザーを標準アドバイザーのリスト中から見つけられない場合に、カスタム・アドバイザーのリストを調べます。アドバイザーの使用に関する追加情報は「WebSphere Application Server Load Balancer 管理ガイド」に記載されています。
カスタム・アドバイザーの名前およびパスについては、以下の要件を忘れないでください。
void ADV_Base Constructor ( string sName; string sVersion; int iDefaultPort; int iInterval; string sDefaultLogFileName; boolean replace )
void ADV_AdvisorInitialize()
このメソッドは、カスタム・アドバイザーに必要な初期化を実行するために提供されます。このメソッドが呼び出されるのはアドバイザー基本モジュールを開始した後です。
標準アドバイザーを含む多くの場合においてこのメソッドは使用されず、そのコードを構成するのは return ステートメントだけです。このメソッドは suppressBaseOpeningSocket メソッドを呼び出すために使用できます。 suppressBaseOpeningSocket メソッドが有効であるのは上記のメソッド内から呼び出された場合のみです。
int getLoad( int iConnectTime; ADV_Thread *caller )
以下のセクションで説明するメソッドまたは関数は、カスタム・アドバイザーから呼び出せます。これらのメソッドはアドバイザー基本コードによってサポートされています。
一部の関数呼び出し (例えば function_name () など) は直接に作成できますが、その他は接頭部 caller を必要とします。caller は基本アドバイザー・インスタンスを示し、これは実行されるカスタム・アドバイザーをサポートします。
ADVLOG 関数により、カスタム・アドバイザーはテキスト・メッセージをアドバイザー基本ログ・ファイルに書き込むことができます。形式は次のとおりです。
void ADVLOG (int logLevel, string message)
getAdvisorName 関数は、カスタム・アドバイザー名の接尾部部分の Java ストリングを戻します。例えば、ADV_cdload.java という名前のアドバイザーでは、この関数は値 cdload を戻します。
この関数にはパラメーターを使用しません。
この値はアドバイザーのインスタンス化中に変更できないことに注意してください。
getAdviseOnPort 関数は、呼び出しカスタム・アドバイザーを実行するポート番号を戻します。戻り値は、 Java 整数 (int) であり、この関数にはパラメーターを使用しません。
この値はアドバイザーのインスタンス化中に変更できないことに注意してください。
getCurrentServer 関数は、現行サーバーの IP アドレスを戻します。戻り値は、IP アドレス形式の Java ストリングです (例えば、128.0.72.139 など)。
アドバイザー基本コードがすべてのサーバー・マシンを続けて照会するため、通常はカスタム・アドバイザーを呼び出すたびにこのアドレスが変更されます。
この関数にはパラメーターを使用しません。
getCurrentCluster 関数呼び出しは、現行サーバー・クラスターの IP アドレスを戻します。戻り値は、IP アドレス形式の Java ストリングです (例えば、128.0.72.139 など)。
アドバイザー基本コードがすべてのサーバー・クラスターを続けて照会するため、通常はカスタム・アドバイザーを呼び出すたびにこのアドレスが変更されます。
この関数にはパラメーターを使用しません。
getInterval 関数は、アドバイザー・サイクル間の秒数であるアドバイザー間隔を戻します。この値は、 dscontrol コマンドを使用して実行時に変更しない限り、カスタム・アドバイザーのコンストラクターに設定されたデフォルト値と同じです。
戻り値は Java 整数 (int) です。この関数にはパラメーターを使用しません。
getLatestLoad 関数により、カスタム・アドバイザーは指定サーバー・オブジェクトの最新ロード値を獲得できます。ロード値は、アドバイザー基本コードおよびマネージャー・デーモンによって内部テーブルで保守されています。
int caller.getLatestLoad (string cluster_IP, int port, string server_IP)
3 つの引数は 1 つのサーバー・オブジェクトをともに定義します。
戻り値は整数です。
この関数呼び出しは、あるプロトコルまたはポートの動作を別のものの動作に依存させる場合に役立ちます。例えば、同一マシン上の Telnet サーバーが使用不可である場合に、特定アプリケーション・サーバーを使用不可にするカスタム・アドバイザーでこの関数呼び出しを使用する場合などです。
receive 関数は、ソケット接続から情報を入手します。
caller.receive(stringbuffer *response)
パラメーター response は、検索されたデータが置かれるストリング・バッファーです。さらに、この関数は以下の重要度のある整数値を戻します。
send 関数は、指定ポートを使用してデータのパケットをサーバーに送信するために確立したソケット接続を使用します。
caller.send(string command)
パラメーター command は、サーバーに送信するデータが入っているストリングです。この関数は、以下の重要度のある整数値を戻します。
suppressBaseOpeningSocket 関数呼び出しにより、カスタム・アドバイザーの代わりに基本アドバイザー・コードがサーバーへの TCP ソケットをオープンするかどうかをカスタム・アドバイザーが指定できます。アドバイザーが状況を判別するためにサーバーとの直接通信を使用しない場合は、このソケットをオープンする必要はありません。
この関数呼び出しを出せるのは一度だけであり、ADV_AdvisorInitialize ルーチンから出さなければなりません。
この関数にはパラメーターを使用しません。
以下の例は、カスタム・アドバイザーをインプリメントできる方法を示します。
このサンプル・ソース・コードは標準 Load Balancer HTTP アドバイザーに類似しています。以下のように機能します。
このアドバイザーは通常モードで操作するので、ロード測定はソケット・オープン、送信、受信、およびクローズ操作を実行するために必要な経過時間 (ミリ秒) に基づきます。
package CustomAdvisors; import com.ibm.internet.lb.advisors.*; public class ADV_sample extends ADV_Base implements ADV_MethodInterface { static final String ADV_NAME ="Sample"; static final int ADV_DEF_ADV_ON_PORT = 80; static final int ADV_DEF_INTERVAL = 7; static final string ADV_SEND_REQUEST = "HEAD / HTTP/1.0¥r¥nAccept: */*¥r\nUser-Agent: " + "IBM_Load_Balancer_HTTP_Advisor\r\n\r\n"; //-------- // Constructor public ADV_sample() { super(ADV_NAME, "3.0.0.0-03.31.00", ADV_DEF_ADV_ON_PORT, ADV_DEF_INTERVAL, "", false); super.setAdvisor( this ); } //-------- // ADV_AdvisorInitialize public void ADV_AdvisorInitialize() { return; // usually an empty routine } //-------- // getLoad public int getLoad(int iConnectTime, ADV_Thread caller) { int iRc; int iLoad = ADV_HOST_INACCESSIBLE; // initialize to inaccessible iRc = caller.send(ADV_SEND_REQUEST); // send the HTTP request to // the server if (0 <= iRc) { // if the send is successful StringBuffer sbReceiveData = new StringBuffer(""); // allocate a buffer // for the response iRc = caller.receive(sbReceiveData); // receive the result // parse the result here if you need to if (0 <= iRc) { // if the receive is successful iLoad = 0; // return 0 for success } // (advisor's load value is ignored by } // base in normal mode) return iLoad; } }
このサンプルでは、アドバイザー・ベースによる標準ソケットのオープンの抑制を例示しています。その代わりに、このアドバイザーはサイド・ストリーム Java ソケットをオープンしてサーバーを照会します。このプロシージャーは、通常のクライアント・トラフィックと異なるポートを使用してアドバイザー照会を listen するサーバーのために役立ちます。
この例では、サーバーはポート 11999 上で listen していて、照会されたときに 16 進 int "4" でロード値を戻します。このサンプルは置換モードで実行されます。つまり、アドバイザー・コンストラクターの最終パラメーターが true に設定されて、アドバイザー基本コードは経過時間ではなく戻されたロード値を使用します。
初期化ルーチンでの supressBaseOpeningSocket() に対する呼び出しに注意してください。データが送信されないときの基本ソケットの抑制は不要です。例えば、アドバイザーがサーバーに接続できることを確認するためにソケットをオープンする場合などです。この選択を行う前には、アプリケーションの必要性を注意深く調べてください。
package CustomAdvisors; import java.io.*; import java.net.*; import java.util.*; import java.util.Date; import com.ibm.internet.lb.advisors.*; import com.ibm.internet.lb.common.*; import com.ibm.internet.lb.server.SRV_ConfigServer; public class ADV_sidea extends ADV_Base implements ADV_MethodInterface { static final String ADV_NAME = "sidea"; static final int ADV_DEF_ADV_ON_PORT = 12345; static final int ADV_DEF_INTERVAL = 7; // create an array of bytes with the load request message static final byte[] abHealth = {(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04}; public ADV_sidea() { super(ADV_NAME, "3.0.0.0-03.31.00", ADV_DEF_ADV_ON_PORT, ADV_DEF_INTERVAL, "", true); // replace mode parameter is true super.setAdvisor( this ); } //-------- // ADV_AdvisorInitialize public void ADV_AdvisorInitialize() { suppressBaseOpeningSocket(); // tell base code not to open the // standard socket return; } //-------- // getLoad public int getLoad(int iConnectTime, ADV_Thread caller) { int iRc; int iLoad = ADV_HOST_INACCESSIBLE; // -1 int iControlPort = 11999; // port on which to communicate with the server string sServer = caller.getCurrentServer(); // address of server to query try { socket soServer = new Socket(sServer, iControlPort); // open socket to // server DataInputStream disServer = new DataInputStream( soServer.getInputStream()); DataOutputStream dosServer = new DataOutputStream( soServer.getOutputStream()); int iRecvTimeout = 10000; // set timeout (in milliseconds) // for receiving data soServer.setSoTimeout(iRecvTimeout); dosServer.writeInt(4); // send a message to the server dosServer.flush(); iLoad = disServer.readByte(); // receive the response from the server } catch (exception e) { system.out.println("Caught exception " + e); } return iLoad; // return the load reported from the server } }
このカスタム・アドバイザー・サンプルは、サーバーの 1 つのポートに対する失敗を検出する機能を説明しています。これは、そのポートの状況と、同一サーバー・マシン上にある別のポート上で実行されている異なるサーバー・デーモンの状況の両方に基づいています。例えば、ポート 80 の HTTP デーモンが応答を停止する場合には、ポート 443 の SSL デーモンへのルーティング・トラフィックも停止することができます。
このアドバイザーは、応答を送信しないサーバーは機能を停止したと見なして、ダウンのマークを付けるので、標準アドバイザーよりも積極的です。標準アドバイザーは応答のないサーバーを非常に低速であると見なします。このアドバイザーは HTTP ポートおよび SSL ポートのいずれかの応答がないと、両方のポートがダウンしたことを示すマークをサーバーに付けます。
このカスタム・アドバイザーを使用するには、アドバイザーの HTTP ポート上にあるインスタンスと SSL ポート上にあるインスタンスを管理者が開始します。アドバイザーは HTTP 用と SSL 用の 2 つの静的グローバル・ハッシュ・テーブルを検証します。各アドバイザーはそのサーバー・デーモンとの通信を試行し、そのハッシュ・テーブルにこのイベントの結果を保管します。各アドバイザーが基本アドバイザー・クラスに戻す値は、その固有のサーバー・デーモンと通信する能力およびそのデーモンと通信するパートナー・アドバイザーの能力によって異なります。
以下のカスタム・メソッドが使用されます。
次のエラー条件が検出されます。
このサンプルは HTTP 用のポート 80 および SSL 用の 443 をリンクするように書かれていますが、ポートの組み合わせは任意に調整できます。
package CustomAdvisors; import java.io.*; import java.net.*; import java.util.*; import java.util.Date; import com.ibm.internet.lb.advisors.*; import com.ibm.internet.lb.common.*; import com.ibm.internet.lb.manager.*; import com.ibm.internet.lb.server.SRV_ConfigServer; //-------- // Define the table element for the hash tables used in this custom advisor class ADV_nte implements Cloneable { private string sCluster; private int iPort; private string sServer; private int iLoad; private Date dTimestamp; //-------- // constructor public ADV_nte(string sClusterIn, int iPortIn, string sServerIn, int iLoadIn) { sCluster = sClusterIn; iPort = iPortIn; sServer = sServerIn; iLoad = iLoadIn; dTimestamp = new Date(); } //-------- // check whether this element is current or expired public boolean isCurrent(ADV_twop oThis) { boolean bCurrent; int iLifetimeMs = 3 * 1000 * oThis.getInterval(); // set lifetime as // 3 advisor cycles Date dNow = new Date(); Date dExpires = new Date(dTimestamp.getTime() + iLifetimeMs); if (dNow.after(dExpires)) { bCurrent = false; } else { bCurrent = true; } return bCurrent; } //-------- // value accessor(s) public int getLoadValue() { return iLoad; } //-------- // clone (avoids corruption between threads) public synchronized Object Clone() { try { return super.clone(); } catch (cloneNotSupportedException e) { return null; } } } //-------- // define the custom advisor public class ADV_twop extends ADV_Base implements ADV_MethodInterface, ADV_AdvisorVersionInterface { static final int ADV_TWOP_PORT_HTTP = 80; static final int ADV_TWOP_PORT_SSL = 443; //-------- // define tables to hold port-specific history information static HashTable htTwopHTTP = new Hashtable(); static HashTable htTwopSSL = new Hashtable(); static final String ADV_TWOP_NAME = "twop"; static final int ADV_TWOP_DEF_ADV_ON_PORT = 80; static final int ADV_TWOP_DEF_INTERVAL = 7; static final string ADV_HTTP_REQUEST_STRING = "HEAD / HTTP/1.0¥r¥nAccept: */*¥r¥nUser-Agent: " + "IBM_LB_Custom_Advisor¥r¥n¥r¥n"; //-------- // create byte array with SSL client hello message public static final byte[] abClientHello = { (byte)0x80, (byte)0x1c, (byte)0x01, // client hello (byte)0x03, (byte)0x00, // SSL version (byte)0x00, (byte)0x03, // cipher spec len (bytes) (byte)0x00, (byte)0x00, // session ID len (bytes) (byte)0x00, (byte)0x10, // challenge data len (bytes) (byte)0x00, (byte)0x00, (byte)0x03, // cipher spec (byte)0x1A, (byte)0xFC, (byte)0xE5, (byte)Ox20, // challenge data (byte)0xFD, (byte)0x3A, (byte)0x3C, (byte)0x18, (byte)0xAB, (byte)0x67, (byte)0xB0, (byte)0x52, (byte)0xB1, (byte)0x1D, (byte)0x55, (byte)0x44, (byte)0x0D, (byte)0x0A }; //-------- // constructor public ADV_twop() { super(ADV_TWOP_NAME, VERSION, ADV_TWOP_DEF_ADV_ON_PORT, ADV_TWOP_DEF_INTERVAL, "", false); // false = load balancer times the response setAdvisor ( this ); } //-------- // ADV_AdvisorInitialize public void ADV_AdvisorInitialize() { return; } //-------- // synchronized PUT and GET access routines for the hash tables synchronized ADV_nte getNte(Hashtable ht, String sName, String sHashKey) { ADV_nte nte = (ADV_nte)(ht.get(sHashKey)); if (null != nte) { nte = (ADV_nte)nte.clone(); } return nte; } synchronized void putNte(Hashtable ht, String sName, String sHashKey, ADV_nte nte) { ht.put(sHashKey,nte); return; } //-------- // getLoadHTTP - determine HTTP load based on server response int getLoadHTTP(int iConnectTime, ADV_Thread caller) { int iLoad = ADV_HOST_INACCESSIBLE; int iRc = caller.send(ADV_HTTP_REQUEST_STRING); // send request message // to server if (0 <= iRc) { // did the request return a failure? StringBuffer sbReceiveData = new StringBuffer("") // allocate a buffer // for the response iRc = caller.receive(sbReceiveData); // get response from server if (0 <= iRc) { // did the receive return a failure? if (0 < sbReceiveData.length()) { // is data there? iLoad = SUCCESS; // ignore retrieved data and // return success code } } } return iLoad; } //-------- // getLoadSSL() - determine SSL load based on server response int getLoadSSL(int iConnectTime, ASV_Thread caller) { int iLoad = ADV_HOST_INACCESSIBLE; int iSocket = caller.getAdvisorSocket(); // send hex request to server CMNByteArrayWrapper cbawClientHello = new CMNByteArrayWrapper( abClientHello); int iRc = SRV_ConfigServer.socketapi.sendBytes(iSocket, cbawClientHello); if (0 <= iRc) { // did the request return a failure? StringBuffer sbReceiveData = new StringBuffer(""); // allocate buffer // for the response iRc = caller.receive(sbReceiveData); // get a response from // the server if (0 <= iRc) { // did the receive return a failure? if (0 < sbReceiveData.length()) { // is data there? iLoad = SUCCESS; // ignore retrieved data and return success code } } } return iLoad; } //-------- // getLoad - merge results from the HTTP and SSL methods public int getLoad(int iConnectTime, ADV_Thread caller) { int iLoadHTTP; int iLoadSSL; int iLoad; int iRc; String sCluster = caller.getCurrentCluster(); // current cluster address int iPort = getAdviseOnPort(); String sServer = caller.getCurrentServer(); String sHashKey = sCluster = ":" + sServer; // hash table key if (ADV_TWOP_PORT_HTTP == iPort) { // handle an HTTP server iLoadHTTP = getLoadHTTP(iConnectTime, caller); // get the load for HTTP ADV_nte nteHTTP = newADV_nte(sCluster, iPort, sServer, iLoadHTTP); putNte(htTwopHTTP, "HTTP", sHashKey, nteHTTP); // save HTTP load // information ADV_nte nteSSL = getNte(htTwopSSL, "SSL", sHashKey); // get SSL // information if (null != nteSSL) { if (true == nteSSL.isCurrent(this)) { // check the time stamp if (ADV_HOST_INACCESSIBLE != nteSSL.getLoadValue()) { // is SSL // working? iLoad = iLoadHTTP; } else { // SSL is not working, so mark the HTTP server down iLoad= ADV_HOST_INACCESSIBLE; } } else { // SSL information is expired, so mark the // HTTP server down iLoad = ADV_HOST_INACCESSIBLE; } } else { // no load information about SSL, report // getLoadHTTP() results iLoad = iLoadHTTP; } } else if (ADV_TWOP_PORT_SSL == iPort) { // handle an SSL server iLoadSSL = getLoadSSL(iConnectTime, caller); // get load for SSL ADV_nte nteSSL = new ADV_nte(sCluster, iPort, sServer, iLoadSSL); putNte(htTwopSSL, "SSL", sHashKey, nteSSL); // save SSL load info. ADV_nte nteHTTP = getNte(htTwopHTTP, "SSL", sHashKey); // get HTTP // information if (null != nteHTTP) { if (true == nteHTTP.isCurrent(this)) { // check the timestamp if (ADV_HOST_INACCESSIBLE != nteHTTP.getLoadValue()) { // is HTTP // working? iLoad = iLoadSSL; } else { // HTTP server is not working, so mark SSL down iLoad = ADV_HOST_INACCESSIBLE; } } else { // expired information from HTTP, so mark SSL down iLoad = ADV_HOST_INACCESSIBLE; } } else { // no load information about HTTP, report // getLoadSSL() results iLoad = iLoadSSL; } } //-------- // error handler else { iLoad = ADV_HOST_INACCESSIBLE; } return iLoad; } }
WebSphere Application Server のサンプル・カスタム・アドバイザーは、install_path/servers/samples/CustomAdvisors/ ディレクトリーに入っています。完全なコードはこの資料では掲載していません。
完全なアドバイザーはサンプルよりわずかに複雑です。上記の StringTokenizer の例よりコンパクトな特殊化された構文解析ルーチンを追加します。
サンプル・コードの複雑な部分は Java サーブレットにあります。多くのメソッドの中で、サーブレット仕様が必要とする init() および service() という 2 つのメソッドと、 Java.lang.thread クラスが必要とする run() という 1 つのメソッドが、サーブレットに入っています。
サーブレット・コードの関連フラグメントは、以下のようになります。
... public void init(ServletConfig config) throws ServletException { super.init(config); ... _checker = new Thread(this); _checker.start(); } public void run() { setStatus(GOOD); while (true) { if (!getKeepRunning()) return; setStatus(figureLoad()); setLastUpdate(new java.util.Date()); try { _checker.sleep(_interval * 1000); } catch (Exception ignore) { ; } } } public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { ServletOutputStream out = null; try { out = res.getOutputStream(); } catch (Exception e) { ... } ... res.setContentType("text/x-application-LBAdvisor"); out.println(getStatusString()); out.println(getLastUpdate().toString()); out.flush(); return; } ...
アプリケーション・サーバーの既存パーツに対する標準呼び出しを使用したり、またはカスタム・アドバイザーのサーバー側で相対するコードの新規部分を追加して、戻されたロード値を調べてサーバー動作を変更することができます。 Java StringTokenizer クラスおよびその関連メソッドはこの調査の実行を簡単にします。
通常の HTTP コマンドのコンテンツは GET /index.html HTTP/1.0 です。
このコマンドに対する通常の応答は、以下のようになります。
HTTP/1.1 200 OK Date: Mon, 20 November 2000 14:09:57 GMT Server: Apache/1.3.12 (Linux and UNIX) Content-Location: index.html.en Vary: negotiate TCN: choice Last-Modified: Fri, 20 Oct 2000 15:58:35 GMT ETag: "14f3e5-1a8-39f06bab;39f06a02" Accept-Ranges: bytes Content-Length: 424 Connection: close Content-Type: text/html Content-Language: en <!DOCTYPE HTML PUBLIC "-//w3c//DTD HTML 3.2 Final//EN"> <HTML><HEAD><TITLE>Test Page</TITLE></HEAD> <BODY><H1>Apache server</H1> <HR> <P><P>This Web server is running Apache 1.3.12. <P><HR> <P><IMG SRC="apache_pb.gif" ALT=""> </BODY></HTML>
関心のある項目 (特に HTTP 戻りコード) は先頭行に入っています。
HTTP 仕様は戻りコードを分類し、以下のように要約できます。
サーバーが戻す可能性のあるコードが正確に分かる場合は、コードをこの例ほど詳細にする必要はありません。ただし、検出する戻りコードを制限すると、プログラムの将来の柔軟性を制限することになる場合があります。
以下の例は、最小限の HTTP クライアントが入っているスタンドアロン Java プログラムです。この例は HTTP 応答を調べるための単純な汎用パーサーを起動します。
import java.io.*; import java.util.*; import java.net.*; public class ParseTest { static final int iPort = 80; static final String sServer = "www.ibm.com"; static final String sQuery = "GET /index.html HTTP/1.0¥r¥n¥r¥n"; static final String sHTTP10 = "HTTP/1.0"; static final String sHTTP11 = "HTTP/1.1"; public static void main(String[] Arg) { String sHTTPVersion = null; String sHTTPReturnCode = null; String sResponse = null; int iRc = 0; BufferedReader brIn = null; PrintWriter psOut = null; Socket soServer= null; StringBuffer sbText = new StringBuffer(40); try { soServer = new Socket(sServer, iPort); brIn = new BufferedReader(new InputStreamReader( soServer.getInputStream())); psOut = new PrintWriter(soServer.getOutputStream()); psOut.println(sQuery); psOut.flush(); sResponse = brIn.readLine(); try { soServer.close(); } catch (Exception sc) {;} } catch (Exception swr) {;} StringTokenizer st = new StringTokenizer(sResponse, " "); if (true == st.hasMoreTokens()) { sHTTPVersion = st.nextToken(); if (sHTTPVersion.equals(sHTTP110) || sHTTPVersion.equals(sHTTP11)) { System.out.println("HTTP Version: " + sHTTPVersion); } else { System.out.println("Invalid HTTP Version: " + sHTTPVersion); } } else { System.out.println("Nothing was returned"); return; } if (true == st.hasMoreTokens()) { sHTTPReturnCode = st.nextToken(); try { iRc = Integer.parseInt(sHTTPReturnCode); } catch (NumberFormatException ne) {;} switch (iRc) { case(200): System.out.println("HTTP Response code: OK, " + iRc); break; case(400): case(401): case(402): case(403): case(404): System.out.println("HTTP Response code: Client Error, " + iRc); break; case(500): case(501): case(502): case(503): System.out.println("HTTP Response code: Server Error, " + iRc); break; default: System.out.println("HTTP Response code: Unknown, " + iRc); break; } } if (true == st.hasMoreTokens()) { while (true == st.hasMoreTokens()) { sbText.append(st.nextToken()); sbText.append(" "); } System.out.println("HTTP Response phrase: " + sbText.toString()); } } }