このトピックでは、Java ランタイムでインスタンスのライフサイクルフックを実装する方法について説明します。
背景情報
インスタンスのライフサイクルフックを実装して設定すると、Function Compute は、関連するライフサイクルイベントが発生したときに、対応するフックを呼び出します。Java ランタイムは、Initializer と PreStop のインスタンスライフサイクルフックをサポートしています。詳細については、「インスタンスライフサイクルの設定」をご参照ください。
インスタンスのライフサイクルフックの課金ルールは、通常の関数呼び出しと同じです。ただし、実行ログは [リアルタイムログ]、[関数ログ]、または [高度なログ] でのみ表示できます。フックログは [呼び出しリクエスト一覧] には表示されません。詳細については、「インスタンスライフサイクルフックのログの表示」をご参照ください。
フックメソッドのシグネチャ
Initializer フックのシグネチャ
Initializer フックは、関数インスタンスの起動後、リクエストハンドラが実行される前に実行されます。Function Compute は、インスタンスのライフサイクル中に Initializer フックが 1 回だけ正常に実行されることを保証します。最初の実行で Initializer フックが失敗した場合、関数の呼び出しは直ちに失敗します。次回の呼び出しでは、Function Compute は新しい関数インスタンスを作成して Initializer フックを実行します。
Initializer フックがタイムアウトまたは失敗した場合、サーバーは常に HTTP 200 状態コードを返します。初期化の失敗がエラーの原因であるかどうかを判断するには、応答ヘッダーの X-Fc-Error-Type:InitializationError または応答本文の errorMessage フィールドを確認します。
Initializer フックには、入力パラメーターが 1 つだけあります (context)。このパラメーターは、リクエストハンドラ (Handler) と同じ方法で使用されます。
Initializer フックを使用するには、FunctionInitializer インターフェイスを継承し、その initialize メソッドを実装します。インターフェイスは次のように定義されています。
package com.aliyun.fc.runtime;
import java.io.IOException;
/**
* これは初期化操作のインターフェイスです
*/
public interface FunctionInitializer {
/**
* Function Compute の初期化リクエストを処理するインターフェイス
*
* @param context Function Compute の初期化環境コンテキストオブジェクト。
* @throws IOException I/O 処理中の IOException
*/
void initialize(Context context) throws IOException;
}PreStop フックのシグネチャ
PreStop フックは、関数インスタンスが破棄される前に実行されます。PreStop フックを使用するには、PreStopHandler インターフェイスを継承し、その preStop メソッドを実装します。インターフェイスは次のように定義されています。
package com.aliyun.fc.runtime;
import java.io.IOException;
/**
* これは preStop 操作のインターフェイスです
*/
public interface PreStopHandler {
/**
* Function Compute の preStop リクエストを処理するインターフェイス
*
* @param context Function Compute の preStop 環境コンテキストオブジェクト。
* @throws IOException I/O 処理中の IOException
*/
void preStop(Context context) throws IOException;
}簡単な例: ストリームリクエストハンドラ
package example;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.aliyun.fc.runtime.Context;
import com.aliyun.fc.runtime.StreamRequestHandler;
import com.aliyun.fc.runtime.FunctionInitializer;
import com.aliyun.fc.runtime.PreStopHandler;
public class App implements StreamRequestHandler, FunctionInitializer, PreStopHandler {
@Override
public void initialize(Context context) throws IOException {
context.getLogger().info("initialize start ...");
}
@Override
public void handleRequest(
InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
context.getLogger().info("handlerRequest ...");
outputStream.write(new String("hello world\n").getBytes());
}
@Override
public void preStop(Context context) throws IOException {
context.getLogger().info("preStop start ...");
}
}InputStream はストリーミングをサポートしています。OutputStream は応答データのストリーミングをサポートしていません。
ライフサイクルフックの設定
コンソールを使用した設定
Function Compute コンソールでは、FC 関数の設定の セクションでライフサイクルフックを設定できます。フックのフォーマットは [パッケージ名].[クラス名]::[メソッド名] です。
Initializer フック: このフィールドを
example.App::initializeに設定します。これは、exampleパッケージの App.java ファイル内のinitializeメソッドを指定します。PreStop フック: このフィールドを
example.App::preStopに設定します。これは、exampleパッケージの App.java ファイル内のpreStopメソッドを指定します。
Serverless Devs を使用した設定
Serverless Devs を使用する場合は、[Initializer フック] と [PreStop フック] の設定を s.yaml ファイルに追加します。
Initializer フックの設定
function 設定に instanceLifecycleConfig.initializer フィールドを追加します。このフィールドには handler と timeout フィールドが含まれます。
PreStop フックの設定
function 設定に instanceLifecycleConfig.preStop フィールドを追加します。このフィールドには handler と timeout フィールドが含まれます。
以下に例を示します。
# ------------------------------------
# 公式マニュアル: https://manual.serverless-devs.com/user-guide/aliyun/#fc3
# ヒント: https://manual.serverless-devs.com/user-guide/tips/
# ご不明な点がある場合は、DingTalk グループ 33947367 に参加してヘルプをご利用ください。
# ------------------------------------
edition: 3.0.0
name: hello-world-app
access: "default"
vars: # グローバル変数
region: "cn-hangzhou"
resources:
hello_world:
component: fc3
actions:
pre-${regex('deploy|local')}:
- run: mvn package -DskipTests
path: ./
props:
region: ${vars.region}
functionName: "start-java-1xqf"
description: 'hello world by serverless devs'
runtime: "java8"
code: ./target/HelloFCJava-1.0-SNAPSHOT-jar-with-dependencies.jar
handler: example.App::handleRequest
memorySize: 128
timeout: 10
instanceLifecycleConfig: # 拡張機能
initializer: # Initializer 関数
handler: example.App::initialize
timeout: 60
preStop: # PreStop 関数
handler: example.App::preStop # 関数のエントリポイント
timeout: 60 # タイムアウト
Serverless Devs の YAML 設定仕様の詳細については、「一般的な Serverless Devs コマンド」をご参照ください。
インスタンスライフサイクルフックのログの表示
[ログ] でライフサイクルフックのログを表示できます。
Function Compute コンソールにログインします。左側のナビゲーションウィンドウで、 を選択します。
上部のナビゲーションバーで、リージョンを選択します。[関数] ページで、ターゲット関数をクリックします。
関数詳細ページで、[関数のテスト] タブをクリックし、[関数のテスト] をクリックしてから、 を選択します。
[ログ] タブで、関数の呼び出しログと Initializer ログを表示できます。例:
2024-03-04 17:57:28FC Initialize Start RequestId: 1-65e59b07-1520da26-bf73bbb91b69 2024-03-04 17:57:282024-03-04 09:57:28.192 1-65e59b07-1520da26-bf73bbb91b69 [info] initializer 2024-03-04 17:57:28FC Initialize End RequestId: 1-65e59b07-1520da26-bf73bbb91b69 2024-03-04 17:57:28FC Invoke Start RequestId: 1-65e59b07-1520da26-bf73bbb91b69 2024-03-04 17:57:28FC Invoke End RequestId: 1-65e59b07-1520da26-bf73bbb91b69各関数インスタンスは一定期間キャッシュされ、すぐには破棄されないため、PreStop フックのログをすぐに表示することはできません。PreStop フックをすばやくトリガーするには、関数の設定または関数コードを更新します。更新が完了すると、[関数ログ] で PreStop フックのログを表示できます。次のサンプルコードに例を示します。
2024-03-04 18:33:26FC PreStop Start RequestId: 93c93603-9fbe-4576-9458-193c8b213031 2024-03-04 18:33:262024-03-04 10:33:26.077 93c93603-9fbe-4576-9458-193c8b213031 [info] preStop 2024-03-04 18:33:26FC PreStop End RequestId: 93c93603-9fbe-4576-9458-193c8b213031
サンプルプログラム
java11-mysql: Initializer フックと PreStop フックをデモする Function Compute のサンプルプログラムです。
この例では、Java ランタイムで Initializer フックを使用して、環境変数からデータベース設定を取得し、MySQL 接続を作成する方法を示します。また、PreStop フックを使用して MySQL 接続を閉じる方法も示します。