機能
このセクションでは、Spring Cloud Task の使用方法、設定方法、適切な拡張ポイントなど、Spring Cloud Task について詳しく説明します。
Spring Cloud Task のライフサイクル
ほとんどの場合、最新のクラウド環境は、終了が予想されないプロセスの実行を中心に設計されています。終了した場合、通常は再起動されます。ほとんどのプラットフォームには、終了時に再起動されないプロセスを実行する何らかの方法がありますが、通常、その実行結果は消耗的な方法で維持されません。Spring Cloud Task は、環境内で短期間のプロセスを実行し、結果を記録する機能を提供します。そうすることで、メッセージによるタスクの統合を通じて、存続期間の短いプロセスだけでなく、長時間実行されるサービスを中心としたマイクロサービスアーキテクチャが可能になります。
この機能はクラウド環境では便利ですが、従来の デプロイモデルでも同じ問題が発生する可能性があります。cron などのスケジューラーを使用して Spring Boot アプリケーションを実行する場合、完了後にアプリケーションの結果を監視できると便利です。
Spring Cloud Task は、Spring Boot アプリケーションが開始と終了を持ちながらも成功できるというアプローチを採用しています。バッチアプリケーションは、終了が予想されるプロセス (多くの場合、有効期間が短い) がどのように役立つかを示す 1 つの例です。
Spring Cloud Task は、特定のタスクのライフサイクルイベントを記録します。ほとんどの Web アプリケーションに代表される、長時間実行プロセスのほとんどは、ライフサイクルイベントを保存しません。Spring Cloud Task の中心となるタスクはこれを実行します。
ライフサイクルは単一のタスクの実行で構成されます。これは、タスクとして構成された Spring Boot アプリケーションの物理的な実行です (つまり、Sprint Cloud タスクの依存関係があります)。
タスクの開始時、CommandLineRunner
または ApplicationRunner
実装が実行される前に、開始イベントを記録する TaskRepository
内のエントリが作成されます。このイベントは、Spring Framework によってトリガーされる SmartLifecycle#start
によってトリガーされます。これは、すべての Bean が使用できる状態にあり、Spring Boot によって提供される CommandLineRunner
または ApplicationRunner
実装を実行する前に行われることをシステムに示します。
タスクの記録は、ApplicationContext のブートストラップが成功した場合にのみ行われます。コンテキストがブートストラップにまったく失敗した場合、タスクの実行は記録されません。 |
Spring Boot からの *Runner#run
呼び出しがすべて完了するか、ApplicationContext
が失敗する ( ApplicationFailedEvent
によって示される) と、タスクの実行が結果とともにリポジトリ内で更新されます。
アプリケーションがタスクの補完時に ApplicationContext を閉じる必要がある場合 (すべての *Runner#run メソッドが呼び出され、タスクリポジトリが更新されている場合)、プロパティ spring.cloud.task.closecontextEnabled を true に設定します。 |
TaskExecution
TaskRepository
に格納される情報は TaskExecution
クラスでモデル化され、次の情報で構成されます。
フィールド | 説明 |
---|---|
| タスクの実行の一意の ID。 |
|
|
| 構成された |
|
|
|
|
| 退出時に入手可能な情報。これは、 |
| 例外がタスク終了の原因である場合 ( |
| 実行可能 Boot アプリケーションに渡された文字列コマンドライン引数の |
終了コードのマッピング
タスクが完了すると、OS に終了コードを返そうとします。元の例を見ると、アプリケーションのその側面を制御していないことがわかります。例外がスローされた場合、JVM はデバッグに役立つかどうかわからないコードを返します。
そのため、Spring Boot は、キャッチされなかった例外を終了コードにマップできるインターフェース ExitCodeExceptionMapper
を提供します。そうすることで、何が問題だったのかを終了コードのレベルで示すことができます。また、この方法で終了コードをマッピングすることにより、Spring Cloud Task は返された終了コードを記録します。
タスクが SIG-INT または SIG-TERM で終了する場合、コード内で特に指定されていない限り、終了コードは 0 です。
タスクの実行中、終了コードはリポジトリに null として保存されます。タスクが完了すると、このセクションで前述したガイドラインに基づいて、適切な終了コードが保存されます。 |
構成
Spring Cloud Task は、DefaultTaskConfigurer
クラスおよび SimpleTaskConfiguration
クラスで定義されているように、すぐに使用できる構成を提供します。このセクションでは、デフォルト設定と、ニーズに合わせて Spring Cloud Task をカスタマイズする方法について説明します。
データソース
Spring Cloud Task は、タスクの実行結果を保存するためにデータソースを使用します。デフォルトでは、H2 のメモリ内インスタンスを提供して、ブートストラップ開発の簡単な方法を提供します。ただし、本番環境では、おそらく独自の DataSource
を構成する必要があるでしょう。
アプリケーションが単一の DataSource
のみを使用し、それがビジネススキーマとタスクリポジトリの両方として機能する場合、必要なのは DataSource
を提供することだけです (これを行う最も簡単な方法は、Spring Boot の構成規則を使用することです)。この DataSource
は、Spring Cloud Task によってリポジトリとして自動的に使用されます。
アプリケーションが複数の DataSource
を使用する場合は、適切な DataSource
を使用してタスクリポジトリを構成する必要があります。このカスタマイズは、TaskConfigurer
の実装を通じて実行できます。
テーブルプレフィックス
TaskRepository
の変更可能なプロパティの 1 つは、タスクテーブルのテーブルプレフィックスです。デフォルトでは、すべての先頭に TASK_
が付きます。TASK_EXECUTION
と TASK_EXECUTION_PARAMS
が 2 つの例です。ただし、このプレフィックスを変更する潜在的な理由があります。スキーマ名をテーブル名の先頭に追加する必要がある場合、または同じスキーマ内に複数のタスクテーブルのセットが必要な場合は、テーブルのプレフィックスを変更する必要があります。これを行うには、次のように spring.cloud.task.tablePrefix
を必要なプレフィックスに設定します。
spring.cloud.task.tablePrefix=yourPrefix
spring.cloud.task.tablePrefix
を使用することにより、ユーザーは、タスクテーブルスキーマの条件を満たし、かつユーザーのビジネスニーズに必要な変更を加えたタスクテーブルを作成する責任を負います。ここに示すように、独自のタスク DDL を作成するときのガイドとして Spring Cloud Task スキーマ DDL を利用できます。
テーブルの初期化を有効 / 無効にする
タスクテーブルを作成していて、タスクの開始時に Spring Cloud Task にタスクテーブルを作成させたくない場合は、次のように spring.cloud.task.initialize-enabled
プロパティを false
に設定します。
spring.cloud.task.initialize-enabled=false
デフォルトは true
です。
プロパティ spring.cloud.task.initialize.enable は非推奨になりました。 |
外部で生成されたタスク ID
場合によっては、タスクがリクエストされたときと、インフラストラクチャが実際にタスクを起動するときとの間の時間差を考慮したい場合があります。Spring Cloud Task を使用すると、タスクがリクエストされたときに TaskExecution
を作成できます。次に、生成された TaskExecution
の実行 ID をタスクに渡し、タスクのライフサイクルを通じて TaskExecution
を更新できるようにします。
TaskExecution
は、TaskExecution
オブジェクトを保持するデータストアを参照する TaskRepository
の実装で createTaskExecution
メソッドを呼び出すことによって作成できます。
生成された TaskExecutionId
を使用するようにタスクを構成するには、次のプロパティを追加します。
spring.cloud.task.executionid=yourtaskId
外部タスク ID
Spring Cloud Task を使用すると、各 TaskExecution
の外部タスク ID を保存できます。生成された TaskExecutionId
を使用するようにタスクを構成するには、次のプロパティを追加します。
spring.cloud.task.external-execution-id=<externalTaskId>
親タスク ID
Spring Cloud Task を使用すると、各 TaskExecution
の親タスク ID を保存できます。この例としては、別のタスクを実行するタスクがあり、どのタスクが各子タスクを起動したかを記録したい場合があります。親 TaskExecutionId
を設定するようにタスクを構成するには、子タスクに次のプロパティを追加します。
spring.cloud.task.parent-execution-id=<parentExecutionTaskId>
TaskConfigurer
TaskConfigurer
は、Spring Cloud Task のコンポーネントの構成方法をカスタマイズできる戦略インターフェースです。デフォルトでは、論理デフォルトを提供する DefaultTaskConfigurer
が提供されます。Map
ベースのメモリ内コンポーネント (DataSource
が提供されない場合に開発に役立ちます) および JDBC ベースのコンポーネント (DataSource
が利用可能な場合に役立ちます)。
TaskConfigurer
では、次の 3 つの主要コンポーネントを構成できます。
コンポーネント | 説明 | デフォルト (DefaultTaskConfigurer によって提供されました) |
---|---|---|
| 使用する |
|
| 使用される |
|
| タスクの更新を実行するときに使用されるトランザクションマネージャー。 |
|
You can customize any of the components described in the preceding table by creating a
custom implementation of the TaskConfigurer
interface. Typically, extending the
DefaultTaskConfigurer
(which is provided if a TaskConfigurer
is not found) and
overriding the required getter is sufficient. However, implementing your own from scratch
may be required.
Users should not directly use getter methods from a TaskConfigurer directly
unless they are using it to supply implementations to be exposed as Spring Beans.
|
Task Execution Listener
TaskExecutionListener
lets you register listeners for specific events that occur during
the task lifecycle. To do so, create a class that implements the
TaskExecutionListener
interface. The class that implements the TaskExecutionListener
interface is notified of the following events:
-
onTaskStartup
: Prior to storing theTaskExecution
into theTaskRepository
. -
onTaskEnd
: Prior to updating theTaskExecution
entry in theTaskRepository
and marking the final state of the task. -
onTaskFailed
: Prior to theonTaskEnd
method being invoked when an unhandled exception is thrown by the task.
Spring Cloud Task also lets you add TaskExecution
Listeners to methods within a bean
by using the following method annotations:
-
@BeforeTask
: Prior to the storing theTaskExecution
into theTaskRepository
@AfterTask
: タスクの最終状態をマークするTaskRepository
内のTaskExecution
エントリを更新する前。@FailedTask
: 未処理の例外がタスクによってスローされたときに@AfterTask
メソッドが呼び出される前。
次の例は、使用されている 3 つのアノテーションを示しています。
public class MyBean {
@BeforeTask
public void methodA(TaskExecution taskExecution) {
}
@AfterTask
public void methodB(TaskExecution taskExecution) {
}
@FailedTask
public void methodC(TaskExecution taskExecution, Throwable throwable) {
}
}
TaskLifecycleListener が存在する前に ApplicationListener を チェーン に挿入すると、予期しない影響が生じる可能性があります。 |
タスク実行リスナーによってスローされる例外
TaskExecutionListener
イベントハンドラーによって例外がスローされた場合、そのイベントハンドラーのすべてのリスナー処理が停止します。例: 3 つの onTaskStartup
リスナーが開始され、最初の onTaskStartup
イベントハンドラーが例外をスローした場合、他の 2 つの onTaskStartup
メソッドは呼び出されません。ただし、TaskExecutionListeners
の他のイベントハンドラー (onTaskEnd
および onTaskFailed
) が呼び出されます。
TaskExecutionListener
イベントハンドラーによって例外がスローされたときに返される終了コードは、ExitCodeEvent (Javadoc) によって報告された終了コードです。ExitCodeEvent
が発行されない場合、スローされた例外が評価されて、型が ExitCodeGenerator であるかどうかが確認されます。存在する場合は、ExitCodeGenerator
から終了コードを返します。それ以外の場合は、1
が返されます。
onTaskStartup
メソッドで例外がスローされた場合、アプリケーションの終了コードは 1
になります。onTaskEnd
または onTaskFailed
メソッドで例外がスローされた場合、アプリケーションの終了コードは、上で列挙したルールを使用して確立されたコードになります。
onTaskStartup 、onTaskEnd 、または onTaskFailed で例外がスローされた場合、ExitCodeExceptionMapper を使用してアプリケーションの終了コードをオーバーライドすることはできません。 |
終了メッセージ
TaskExecutionListener
を使用すると、タスクの終了メッセージをプログラムで設定できます。これは、TaskExecution’s
exitMessage
を設定することによって行われ、その後 TaskExecutionListener
に渡されます。次の例は、@AfterTask
ExecutionListener
のアノテーションが付けられたメソッドを示しています。
@AfterTask
public void afterMe(TaskExecution taskExecution) {
taskExecution.setExitMessage("AFTER EXIT MESSAGE");
}
ExitMessage
は、リスナーイベント (onTaskStartup
、onTaskFailed
、onTaskEnd
) のいずれかで設定できます。3 つのリスナーの優先順位は次のとおりです。
onTaskEnd
onTaskFailed
onTaskStartup
例: onTaskStartup
および onTaskFailed
リスナーに exitMessage
を設定し、タスクが失敗せずに終了した場合、onTaskStartup
からの exitMessage
がリポジトリに保存されます。それ以外の場合、障害が発生すると、onTaskFailed
から exitMessage
が格納されます。また、onTaskEnd
リスナーを使用して exitMessage
を設定した場合、onTaskEnd
の exitMessage
が、onTaskStartup
と onTaskFailed
の両方からの終了メッセージよりも優先されます。
Spring Cloud Task インスタンスの制限
Spring Cloud Task を使用すると、指定されたタスク名のタスクを一度に 1 つだけ実行できるように設定できます。これを行うには、タスク名を確立し、タスク実行ごとに spring.cloud.task.single-instance-enabled=true
を設定する必要があります。最初のタスクの実行中に、同じタスク名と spring.cloud.task.single-instance-enabled=true
を持つタスクを実行しようとすると、タスクは失敗し、次のエラーメッセージが表示されます。Task with name "application" is already running.
spring.cloud.task.single-instance-enabled
のデフォルト値は false
です。次の例は、spring.cloud.task.single-instance-enabled
を true
に設定する方法を示しています。
spring.cloud.task.single-instance-enabled=true or false
この機能を使用するには、次の Spring Integration 依存関係をアプリケーションに追加する必要があります。
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
</dependency>
この機能が有効になっており、別のタスクが同じタスク名で実行されているためにタスクが失敗した場合、アプリケーションの終了コードは 1 になります。 |
Spring AOT およびネイティブコンパイルの単一インスタンスの使用
ネイティブコンパイルされたアプリの作成時に Spring Cloud Task の単一インスタンス機能を使用するには、ビルド時に機能を有効にする必要があります。これを行うには、次のように process-aot 実行を追加し、JVM 引数として spring.cloud.task.single-step-instance-enabled=true
を設定します。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>process-aot</id>
<goals>
<goal>process-aot</goal>
</goals>
<configuration>
<jvmArguments>
-Dspring.cloud.task.single-instance-enabled=true
</jvmArguments>
</configuration>
</execution>
</executions>
</plugin>
ApplicationRunner および CommandLineRunner の監視の有効化
ApplicationRunner
または CommandLineRunner
のタスク監視を有効にするには、spring.cloud.task.observation.enabled
を true に設定します。
SimpleMeterRegistry
を使用して観察を可能にするタスクアプリケーションの例は、ここにあります。
Spring Cloud Task 自動構成の無効化
Spring Cloud Task を実装用に自動構成すべきでない場合は、タスクの自動構成を無効にすることができます。これを行うには、次のアノテーションをタスクアプリケーションに追加します。
@EnableAutoConfiguration(exclude={SimpleTaskAutoConfiguration.class})
spring.cloud.task.autoconfiguration.enabled
プロパティを false
に設定して、タスクの自動構成を無効にすることもできます。
コンテキストを閉じる
アプリケーションがタスクの補完時に ApplicationContext
を閉じる必要がある場合 (すべての *Runner#run
メソッドが呼び出され、タスクリポジトリが更新されている場合)、プロパティ spring.cloud.task.closecontextEnabled
を true
に設定します。
コンテキストを閉じるもう 1 つのケースは、タスクの実行が完了してもアプリケーションが終了しない場合です。このような場合、スレッドが割り当てられているため、コンテキストは開いたままになります (たとえば、TaskExecutor を使用している場合)。このような場合は、タスクの起動時に spring.cloud.task.closecontextEnabled
プロパティを true
に設定します。これにより、タスクが完了するとアプリケーションのコンテキストが閉じられます。アプリケーションの終了が許可されます。
タスクメトリクスを有効にする
Spring Cloud Task は Micrometer と統合し、実行するタスクの監視を作成します。タスク監視の統合を有効にするには、spring-boot-starter-actuator
、優先レジストリ実装 (メトリクスを公開する場合)、およびマイクロメータートレーシング (トレースデータを公開する場合) をタスクアプリケーションに追加する必要があります。Influx を使用してタスクの可観測性とメトリクスを有効にするための maven 依存関係セットの例は次のようになります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-influx</artifactId>
<scope>runtime</scope>
</dependency>
Spring タスクと Spring Cloud Task プロパティ
task
という用語は業界で頻繁に使用される言葉です。このような例では、Spring Boot は spring.task
を提供し、Spring Cloud Task は spring.cloud.task
プロパティを提供します。このため、これら 2 つのプロパティグループが直接関連しているということで、過去に混乱が生じていました。ただし、これらは Spring エコシステムで提供される 2 つの異なる機能セットを表しています。
spring.task
は、ThreadPoolTaskScheduler
を構成するプロパティを指します。spring.cloud.task
は、Spring Cloud Task の機能を構成するプロパティを指します。