このドキュメントは、ajp13 としても知られる現在の Apache JServ プロトコルバージョン 1.3 の進化に関する提案です。ここではプロトコル全体ではなく、ajp13 からの追加機能のみを扱います。このn回目のパスには、tomcat-dev メーリングリストからのコメントと、開発中に発見された見落としが含まれています。
AJP13 で不足している機能
ajp13 は、Tomcat のようなサーブレットエンジンを Apache のようなWebサーバーにリンクするための優れたプロトコルです。
- 各リクエストでの再接続時間を避けるために永続接続を使用する
- ストリームサイズを削減するために多くのHTTPコマンドをエンコードする
- Webサーバーからサーブレットエンジンに多くの情報(SSL証明書など)を送信する
しかし、ajp13 は以下のサポートが不足しています。
- Webサーバーとサーブレットエンジン間のセキュリティ。誰でも ajp13 ポートに接続でき(ログインメカニズムは使用されない)、例えば telnet で接続し、データを送信しないことでリモートスレッドを維持できます(接続にタイムアウトがない)。
- サーブレットエンジンからWebサーバーに渡されるコンテキスト情報。WebサーバーコネクタであるJKの設定の一部は、どのURIを処理するかをWebサーバーに指示することです。mod_jk の JkMount ディレクティブは、どのURIをサーブレットエンジンに転送すべきかをWebサーバーに伝えます。サーブレットエンジンはすでにどのURIを処理するかを知っており、TC 3.3 は利用可能なコンテキストのリストからJKの構成ファイルを生成できます。
- サーブレットエンジンからWebサーバーへのコンテキストのステータス更新。ISP や仮想ホスティングサービスプロバイダーのような、大規模な Tomcat ファームを持つサイトでは、管理目的でコンテキストを停止する必要がある場合があります。その場合、フロントのWebサーバーはコンテキストが現在ダウンしていることを認識し、最終的にリクエストを別のTomcatに中継する必要があります。
- リクエスト送信前の接続状態の検証。実際には、JK はリクエストをサーブレットエンジンに送信し、次にその応答を待ちます。しかし、ソケットAPIの利点の一つは、クローズされた接続に write() してもエラー報告がないことですが、クローズされた接続から read() するとエラーコードが返されることです。
AJP13 への提案される追加機能
ここでは、AJP13 に追加できる機能とアドオンについて説明します。このドキュメントは提案であるため、最初はある程度の混乱が予想されます。tomcat メーリングリストでの議論が、点を明確にし、機能を追加するのに役立つことは間違いありませんが、現在のリストは「最低限の必須項目」であると思われます。
- 接続時の高度なログイン機能
- Webサーバーとサーブレットエンジンに共通のシークレットキーが存在する、基本的な認証システム。
- 将来的にAJP13に機能が追加されたとしても、現在の実装が引き続き動作することを確実にするための基本的なプロトコルネゴシエーション。
- 「不明なパケット」の適切な処理
- Webサーバーからサーブレットエンジンに渡される拡張環境変数。
- Servlet 2.3 API で必要とされる追加の SSL 情報 (SSL_KEY_SIZE など) を追加
高度なログイン
- WEB-SERVER は LOGIN INIT CMD + NEGOCIATION DATA + WEB SERVER INFO を送信します
- TOMCAT は LOGIN SEED CMD + RANDOM DATA で応答します
- WEB-SERVER は RANDOM DATA + SECRET DATA の MD5 を計算します
- WEB-SERVER は LOGIN COMP CMD + MD5 (SECRET DATA + RANDOM DATA) を送信します
- TOMCAT は LOGIN STATUS CMD + NEGOCIED DATA + SERVLET ENGINE INFO で応答します
メッセージストリーム
+----------------+------------------+-----------------+
| LOGIN INIT CMD | NEGOCIATION DATA | WEB SERVER INFO |
+----------------+------------------+-----------------+
+----------------+----------------+
| LOGIN SEED CMD | MD5 of entropy |
+----------------+----------------+
+----------------+----------------------------+
| LOGIN COMP CMD | MD5 of RANDOM + SECRET KEY |
+----------------+----------------------------+
+-----------+---------------+---------------------+
| LOGOK CMD | NEGOCIED DATA | SERVLET ENGINE INFO |
+-----------+---------------+---------------------+
+------------+--------------+
| LOGNOK CMD | FAILURE CODE |
+------------+--------------+
- LOGIN INIT CMD、LOGIN SEED CMD、LOGIN COMP CMD、LOGOK CMD、LOGNOK CMD は 1 バイト長です。
- MD5、RANDOM + SECRET KEY の MD5 は 32 文字長です。
- NEGOCIATION DATA、NEGOCIED DATA、FAILURE CODE は 32 ビット長です。
- WEB SERVER INFO、SERVLET ENGINE INFO は CString です。
worker.ajp13.port=8009
worker.ajp13.host=localhost
worker.ajp13.type=ajp13
worker.ajp13.secretkey=myverysecretkey
シャットダウン機能
AJP13 は AJP12 の機能であるシャットダウンコマンドを欠いています。ログアウトはサーブレットエンジンに自身をシャットダウンするよう伝えます。
+--------------+----------------------------+
| SHUTDOWN CMD | MD5 of RANDOM + SECRET KEY |
+--------------+----------------------------+
+------------+
| SHUTOK CMD |
+------------+
+-------------+--------------+
| SHUTNOK CMD | FAILURE CODE |
+-------------+--------------+
- SHUTDOWN CMD, SHUTOK CMD, SHUTNOK CMD は 1 バイト長です。
- RANDOM + SECRET KEY の MD5 は 32 文字長です。
- FAILURE CODE は 32 ビット長です。
拡張環境変数機能
注記: JK の AJP13 に取り組んでいる際に、私は「JkEnvVar」を実際に発見しました。以下の「拡張環境変数機能」の説明は、元の実装ですでに利用可能であるため、拡張 AJP13 では実装されない可能性があります。説明: 多くのユーザーは、Webサーバーの環境変数の一部がサーブレットエンジンに渡されることを望むでしょう。ネットワークトラフィックを削減するために、Webサーブレットは外部変数をより簡潔な方法で記述するテーブルを送信します。AJP13 ですでに存在する機能である属性リストを使用します。AJP13 では、
AJP13_FORWARD_REQUEST :=
prefix_code 2
method (byte)
protocol (string)
req_uri (string)
remote_addr (string)
remote_host (string)
server_name (string)
server_port (integer)
is_ssl (boolean)
num_headers (integer)
request_headers *(req_header_name req_header_value)
?context (byte string)
?servlet_path (byte string)
?remote_user (byte string)
?auth_type (byte string)
?query_string (byte string)
?route (byte string)
?ssl_cert (byte string)
?ssl_cipher (byte string)
?ssl_session (byte string)
?attributes *(attribute_name attribute_value)
request_terminator (byte)
+-------------------+---------------------------+-------------------------------+----+
| EXTENDED VARS CMD | WEB SERVER ATTRIBUTE NAME | SERVLET ENGINE ATTRIBUTE NAME | ES |
+-------------------+---------------------------+-------------------------------+----+
JkExtVars S1 SSL_CLIENT_V_START javax.servlet.request.ssl_start_cert_date
JkExtVars S2 SSL_CLIENT_V_END javax.servlet.request.ssl_end_cert_date
JkExtVars S3 SSL_SESSION_ID javax.servlet.request.ssl_session_id
+-------------------+----+-------------------------------------------+
| EXTENDED VARS CMD | S1 | javax.servlet.request.ssl_start_cert_date |
+-------------------+----+-------------------------------------------+
+----+-----------------------------------------+
| S2 | javax.servlet.request.ssl_end_cert_date |
+----+-----------------------------------------+
+----+-----------------------------------------+
| S3 | javax.servlet.request.ssl_end_cert_date |
+----+-----------------------------------------+
- EXTENDED VARS CMD は 1 バイト長です。
- WEB SERVER ATTRIBUTE NAME, SERVLET ENGINE ATTRIBUTE NAME は CString です。
- ES は空の CString です。
サーブレットエンジンからWebサーバーへのコンテキスト情報の転送
ログオンフェーズの直後、Webサーバーはサーブレットエンジンが処理するコンテキストとURL/URIのリストを要求します。これにより、多くのサイトでのインストールが容易になり、tomcat-user メーリングリストでの設定に関する質問が減り、Servlet API 2.3 に対応できるようになります。このモードは、新しいディレクティブ JkAutoMount によってアクティブ化されます。例: JkAutoMount examples myworker1 /examples/ サーブレットエンジンによって処理されるすべてのコンテキストを取得したい場合は、ワイルドカードを使用できます。例: JkAutoMount * myworker1 * サーブレットエンジンは、/examples、/admin、/test など、多くのコンテキストを持つことができます。特定のワーカーに対して一部のコンテキストのみを使用したい場合があります。これは以前、例えば Apache HTTP Server では、Apache の各 [virtual] エリアでJkMountを手動で設定することによって行われていました。Webサーバーが仮想ホスティングをサポートしている場合、その情報もサーブレットエンジンに転送され、サーブレットエンジンはその仮想ホストのコンテキストのみを返します。その場合、サーブレットエンジンはこれらの特定の仮想サーバー(server.xml で定義)に一致するURL/URIのみを返します。この機能は、ロードバランシング構成で大規模なTomcatファームを共有するISPや大規模サイトに役立ちます。
+-----------------+-------------------+----------+----------+----+
| CONTEXT QRY CMD | VIRTUAL HOST NAME | CONTEXTA | CONTEXTB | ES |
+-----------------+-------------------+----------+----------+----+
+------------------+-------------------+----------+-------------------+----------+---------------+----+
| CONTEXT INFO CMD | VIRTUAL HOST NAME | CONTEXTA | URL1 URL2 URL3 ES | CONTEXTB | URL1 URL2 ... | ES |
+------------------+-------------------+----------+-------------------+----------+---------------+----+
- CONTEXT QRY CMD と CONTEXT INFO CMD は 1 バイト長です。
- VIRTUAL HOST NAME は CString、つまりヌルバイト (/0) で終端される文字配列です。
- 空の文字列は単なるヌルバイト (/0) です。
- ES は空の CString です。URI/URL の終わり、または CONTEXT の終わりを示します。
VirtualMode を使用しない場合、VIRTUAL HOST NAME は「*」です。その場合、サーブレットエンジンは処理するすべてのコンテキストを送信します。
サーブレットエンジンからWebサーバーへのコンテキスト情報の更新
コンテキストの更新は、コンテキストが非アクティブ化/再アクティブ化されるたびにサーブレットエンジンから送信されるメッセージです。更新は JkUpdateMount ディレクティブが使用されるときに有効になります。このディレクティブは AJP13_CONTEXT_UPDATE_NEG フラグを設定します。例: JkUpdateMount myworker1
+--------------------+-------------------+----------+--------+----------+--------+----+
| CONTEXT UPDATE CMD | VIRTUAL HOST NAME | CONTEXTA | STATUS | CONTEXTB | STATUS | ES |
+--------------------+-------------------+----------+--------+----------+--------+----+
- CONTEXT UPDATE CMD, STATUS は 1 バイト長です。
- VIRTUAL HOST NAME, CONTEXTS は CString です。
- ES は空の CString です。CONTEXT の終わりを示します。
VirtualMode が使用されていない場合、VIRTUAL HOST NAME は「*」です。STATUS はコンテキストが UP/DOWN/INVALID のいずれかを示す 1 バイトです。
サーブレットエンジンへのコンテキストステータスクエリ
このクエリは、Webサーバーが指定されたコンテキストが UP、DOWN、または INVALID(そして削除されるべき)であるかを判断するために使用されます。
+-------------------+--------------------+----------+----------+----+
| CONTEXT STATE CMD | VIRTUAL HOST NAME | CONTEXTA | CONTEXTB | ES |
+-------------------+--------------------+----------+----------+----+
+-------------------------+-------------------+----------+--------+----------+--------+----+
| CONTEXT STATE REPLY CMD | VIRTUAL HOST NAME | CONTEXTA | STATUS | CONTEXTB | STATUS | ES |
+-------------------------+-------------------+----------+-------------------+--------+----+
- CONTEXT STATE CMD, CONTEXT STATE REPLY CMD, STATUS は 1 バイト長です。
- VIRTUAL HOST NAME, CONTEXTS は CString です
- ES は空の CString です
VirtualMode が使用されていない場合、VIRTUAL HOST NAME は空の文字列です。
不明なパケットの処理
十分にネゴシエートされたプロトコルであっても、Webサーバーまたはサーブレットエンジンのいずれかの一方が理解できないメッセージを受信する状況になることがあります。その場合、受信側は未処理のメッセージを付加した「UNKNOW PACKET CMD」を送信します。
+--------------------+------------------------+-------------------+
| UNKNOWN PACKET CMD | UNHANDLED MESSAGE SIZE | UNHANDLED MESSAGE |
+--------------------+------------------------+-------------------+
- UNKNOWN PACKET CMD は 1 バイト長です。
- UNHANDLED MESSAGE SIZE は 16 ビット長です。
- UNHANDLED MESSAGE はバイト配列です (長さは UNHANDLED MESSAGE SIZE に含まれます)
UNHANDLED MESSAGE SIZE を追加 (開発)
リクエスト送信前の接続の検証
注記: この機能は、リクエストを転送する前にWebサーバー側で追加のI/O(読み取り)を必要とするため、通常のプロセスを遅くする可能性があるため、決して使用されないかもしれません.....ソケットAPIの利点の一つは、半閉じ状態のソケットに書き込めることです。サーブレットエンジンがソケットを閉じると、Webサーバーは次のソケットへの read() の時に初めてそれを発見します。基本的に、AJP13プロトコルでは、WebサーバーがHTTPヘッダーとHTTPボディ(8KBチャンクのPOST)をサーブレットエンジンに送信し、その後応答を受信しようとします。接続が切断されていた場合、Webサーバーは受信時にのみそれを知ることになります。バッファリングスキームを使用することもできますが、8KBを超えるデータでのアップロード操作にサーブレットエンジンを使用した場合、どうなりますか?AJP13プロトコルでのハックは、サービス終了後に読み取るバイトを追加することです。
EXAMPLE OF DISCUSSION BETWEEN WEB SERVER AND SERVLET ENGINE
AJP HTTP-HEADER (+ HTTP-POST) (WEB->SERVLET)
AJP HTTP-REPLY (SERVLET->WEB)
AJP END OF DISCUSSION (SERVLET->WEB)
---> AJP STATUS (SERVLET->WEB AJP13)
+------------+-------------+
| STATUS CMD | STATUS DATA |
+------------+-------------+
- STATUS CMD と STATUS DATA は 1 バイト長です。