システムマネジメント
指標と管理
このセクションでは、Spring Integration のメトリクスをキャプチャーする方法について説明します。最近のバージョンでは、Micrometer(https://micrometer.io (英語) を参照)にさらに依存しており、将来のリリースでは Micrometer をさらに使用する予定です。
メトリクスキャプチャーの構成
| バージョン 4.2 より前は、メトリクスは JMX が有効になっている場合にのみ使用可能でした。JMX サポートを参照してください。 |
MessageSource、MessageChannel、MessageHandler メトリクスを有効にするには、<int:management/> Bean をアプリケーションコンテキスト(XML)に追加するか、@Configuration クラスの 1 つに @EnableIntegrationManagement (Java)でアノテーションを付けます。MessageSource インスタンスはカウントのみを維持し、MessageChannel インスタンスと MessageHandler インスタンスはカウントに加えて期間統計を維持します。この章で後述する MessageChannel メトリクス機能および MessageHandler メトリクス機能を参照してください。
これにより、アプリケーションコンテキストで IntegrationManagementConfigurer Bean が自動的に登録されます。このような Bean はコンテキストに 1 つだけ存在でき、<bean/> 定義を介して手動で登録する場合は、Bean 名を integrationManagementConfigurer に設定する必要があります。この Bean は、コンテキスト内のすべての Bean がインスタンス化された後、その構成を Bean に適用します。
メトリクスに加えて、メインメッセージフローでデバッグロギングを制御できます。非常に大量のアプリケーションでは、isDebugEnabled() の呼び出しでさえ、一部のロギングサブシステムでは非常に高負荷になる可能性があります。このオーバーヘッドを回避するために、このようなロギングをすべて無効にすることができます。例外ロギング(デバッグまたはその他)は、この設定の影響を受けません。
次のリストは、ロギングを制御するために使用可能なオプションを示しています。
<int:management
default-logging-enabled="true" (1)
default-counts-enabled="false" (2)
default-stats-enabled="false" (3)
counts-enabled-patterns="foo, !baz, ba*" (4)
stats-enabled-patterns="fiz, buz" (5)
metrics-factory="myMetricsFactory" /> (6)@Configuration
@EnableIntegration
@EnableIntegrationManagement(
defaultLoggingEnabled = "true", (1)
defaultCountsEnabled = "false", (2)
defaultStatsEnabled = "false", (3)
countsEnabled = { "foo", "${count.patterns}" }, (4)
statsEnabled = { "qux", "!*" }, (5)
MetricsFactory = "myMetricsFactory") (6)
public static class ContextConfiguration {
...
}| 1 | false に設定すると、ログシステムのカテゴリ設定に関係なく、メインメッセージフローのすべてのロギングが無効になります。デバッグログを有効にするには、"true" に設定します(ログサブシステムでも有効になっている場合)。Bean 定義で設定を明示的に構成していない場合にのみ適用されます。デフォルトは true です。 |
| 2 | <4> のパターンのいずれかに一致しないコンポーネントのカウントメトリクスを有効または無効にします。Bean 定義で設定を明示的に構成していない場合にのみ適用されます。デフォルトは false です。 |
| 3 | <5> のパターンのいずれかに一致しないコンポーネントの統計メトリクスを有効または無効にします。Bean 定義で設定を明示的に構成していない場合にのみ適用されます。デフォルトは "false" です。 |
| 4 | カウントを有効にする必要がある Bean のパターンのコンマ区切りリスト。! でパターンを無効にすることができます。最初の一致(正または負)が勝ちます。まれに、! で始まる Bean 名がある場合、パターン内の ! をエスケープします。例: \!something は、!something という名前の Bean と完全に一致します。 |
| 5 | 統計メトリクスを有効にする必要がある Bean のパターンのコンマ区切りリスト。! で pattern \ を無効にすることができます。最初の一致(正または負)が勝ちます。まれに、! で始まる Bean 名がある場合、パターン内の ! をエスケープします。\!something は、!something という名前の Bean と確実に一致します。統計の収集は、カウントの収集を意味します。 |
| 6 | MetricsFactory への参照。メトリクスファクトリを参照してください。 |
実行時に、カウントと統計は、それぞれ MessageChannelMetrics、MessageHandlerMetrics、MessageSourceMetrics を返す getChannelMetrics、getHandlerMetrics、getSourceMetrics (すべて IntegrationManagementConfigurer クラスから)を呼び出すことによって取得できます。
これらのクラスの詳細については、Javadoc を参照してください。
JMX が有効な場合(JMX サポートを参照)、IntegrationMBeanExporter はこれらのメトリクスも公開します。
IMPORTANT: defaultLoggingEnabled、defaultCountsEnabled、defaultStatsEnabled は、Bean 定義で対応する設定を明示的に構成していない場合にのみ適用されます。
バージョン 5.0.2 以降、フレームワークは、アプリケーションコンテキストに単一の MetricsFactory Bean が存在するかどうかを自動的に検出し、存在する場合はデフォルトのメトリクスファクトリの代わりにそれを使用します。
| これらのレガシーメトリクスは、以下で説明する Micrometer メトリクスを推奨して非推奨となりました。レガシーメトリクスのサポートは、将来のリリースで削除される予定です。 |
Micrometer 統合
バージョン 5.0.3 以降、アプリケーションコンテキストに Micrometer (英語) MeterRegistry が存在すると、組み込みメトリクスに加えて Micrometer メトリクスのサポートがトリガーされます(従来の組み込みメトリクスは将来のリリースで削除されることに注意してください)。
Micrometer は、バージョン 5.0.2 で最初にサポートされましたが、バージョン 5.0.3 で Micrometer Meters に変更が加えられ、次元システムでの使用により適したものになりました。5.0.4 ではさらに変更が加えられました。Micrometer を使用する場合、5.0.4 の変更の一部が API の変更を壊していたため、最小限のバージョン 5.0.4 をお勧めします。 |
Micrometer を使用するには、MeterRegistry Bean の 1 つをアプリケーションコンテキストに追加します。IntegrationManagementConfigurer は、MeterRegistry Bean を 1 つだけ検出した場合、integrationMicrometerMetricsCaptor という名前で MicrometerMetricsCaptor Bean を構成します。
MessageHandler および MessageChannel ごとに、タイマーが登録されます。MessageSource ごとに、カウンターが登録されます。
これは、AbstractMessageHandler、AbstractMessageChannel、AbstractMessageSource を継承するオブジェクトにのみ適用されます(ほとんどのフレームワークコンポーネントに当てはまります)。
Micrometer メトリクスでは、統計のキャプチャーは Micrometer に委譲されるため、statsEnabled フラグは効果がありません。countsEnabled フラグは、各メッセージを処理するときに Micrometer Meter インスタンスを更新するかどうかを制御します。
メッセージチャネルの送信操作用の Timer メーターには、次の名前またはタグがあります。
name:spring.integration.sendtag:type:channeltag:name:<componentName>tag:result:(success|failure)tag:exception:(none|exception simple class name)description:Send processing time
(none 例外を含む failure 結果は、チャネルの send() 操作が false を返したことを意味します)
ポーリング可能なメッセージチャネルでの受信操作用の Counter メーターには、次の名前またはタグがあります。
name:spring.integration.receivetag:type:channeltag:name:<componentName>tag:result:(success|failure)tag:exception:(none|exception simple class name)description:Messages received
メッセージハンドラーの操作用の Timer メーターには、次の名前またはタグがあります。
name:spring.integration.sendtag:type:handlertag:name:<componentName>tag:result:(success|failure)tag:exception:(none|exception simple class name)description:Send processing time
メッセージソースの Counter メーターには、次の名前 / タグがあります。
name:spring.integration.receivetag:type:sourcetag:name:<componentName>tag:result:successtag:exception:nonedescription:Messages received
さらに、3 つの Gauge メーターがあります。
spring.integration.channels: アプリケーション内のMessageChannelsの数。spring.integration.handlers: アプリケーション内のMessageHandlersの数。spring.integration.sources: アプリケーション内のMessageSourcesの数。
MicrometerMetricsCaptor のサブクラスを提供することにより、統合コンポーネントによって作成された Meters の名前とタグをカスタマイズできます。MicrometerCustomMetricsTests [GitHub] (英語) テストケースは、その方法の簡単な例を示しています。ビルダーサブクラスの build() メソッドをオーバーロードすることにより、メーターをさらにカスタマイズすることもできます。
MessageChannel メトリクス機能
これらのレガシーメトリクスは、将来のリリースで削除される予定です。Micrometer 統合を参照してください。
メッセージチャネルは、具象型に従ってメトリクスをレポートします。DirectChannel を見ている場合、送信操作の統計が表示されます。QueueChannel の場合、受信操作の統計と、この QueueChannel によって現在バッファリングされているメッセージの数も表示されます。どちらの場合も、一部のメトリクスは単純なカウンター(メッセージカウントとエラーカウント)であり、一部は興味深い量の平均の推定値です。これらの推定値の計算に使用されるアルゴリズムについて、次の表で簡単に説明します。
| メトリクス型 | サンプル | アルゴリズム |
|---|---|---|
カウント | 送信数 | シンプルなインクリメンター。イベントが発生すると 1 ずつ増加します。 |
エラー数 | エラーカウントの送信 | シンプルなインクリメンター。送信でエラーが発生すると、1 ずつ増加します。 |
持続時間 | 送信時間 (ミリ秒単位のメソッド実行時間) | 減衰係数を伴う指数移動平均(デフォルトでは 10)。ほぼ最後の 10 回(デフォルト)の測定でのメソッド実行時間の平均。 |
レート | 送信レート (1 秒あたりの操作数) | 時間の減衰があるイベント間の間隔の指数移動平均の逆数(デフォルトでは 60 秒以上経過)および測定ごと(デフォルトでは最後の 10 イベント)。 |
エラー率 | エラー率を送信 (1 秒あたりのエラー数) | 時間の減衰を伴うエラーイベント(デフォルトでは 60 秒以上)と測定単位(デフォルトでは最後の 10 イベント)の間隔の指数移動平均の逆数。 |
比率 | 成功率を送信 (合計送信に対する成功の比率) | 値で構成される系列の指数移動平均として成功率を推定します(成功の場合は 1、失敗の場合は 0、デフォルトでは時間とイベントに伴うレート測定に従って減衰します)。エラー率は次のとおりです。1- 成功率。 |
MessageHandler メトリクス機能
これらのレガシーメトリクスは、将来のリリースで削除される予定です。Micrometer 統合を参照してください。
次の表は、メッセージハンドラーについて維持される統計を示しています。一部のメトリクスは単純なカウンター(メッセージカウントとエラーカウント)であり、1 つは送信期間の平均の推定値です。これらの推定値の計算に使用されるアルゴリズムについて、次の表で簡単に説明します。
| メトリクス型 | サンプル | アルゴリズム |
|---|---|---|
カウント | ハンドル数 | シンプルなインクリメンター。イベントが発生すると 1 ずつ増加します。 |
エラー数 | ハンドラーのエラー数 | シンプルなインクリメンター。呼び出しでエラーが発生すると、1 ずつ増加します。 |
アクティブカウント | ハンドラーのアクティブカウント | 現在ハンドラー(または任意のダウンストリーム同期フロー)を呼び出している現在アクティブなスレッドの数を示します。 |
持続時間 | 処理時間 (ミリ秒単位のメソッド実行時間) | 減衰係数を伴う指数移動平均(デフォルトでは 10)。およそ最後の 10 回(デフォルト)の測定でのメソッド実行時間の平均。 |
時間ベースの平均推定
時間ベースの平均推定値の特徴は、新しい測定値が到着しなければ時間とともに減衰することです。経時的な動作の解釈に役立つように、最後の測定からの時間(秒単位)もメトリクスとして公開されます。
2 つの基本的な指数モデルがあります: 測定ごとの減衰(期間と測定回数がメトリクスの一部である場合に適切)および時間単位ごとの減衰(測定間の時間がメトリクスの一部であるレート測定により適しています)。両方のモデルは、w(i) = r^i が r=constant: S(n) = x(n) + r S(n-1) の場合、S(n) = sum(i=0,i=n) w(i) x(i) が特別な形式を持っているという事実に依存します(したがって、S(n-1) (シリーズ x(i) 全体ではなく)のみを保存して、最後の測定から新しいメトリクス推定値を生成します)。期間メトリクスで使用されるアルゴリズムは、r=exp(-1/M) と M=10 を使用します。最終的な影響は、推定値 S(n) が最近の測定値により大きく重み付けされ、おおよそ最後の M 測定値で構成されることです。M は推定の「ウィンドウ」または失効率です。バニラ移動平均の場合、i は測定回数のカウンターです。レートについては、i を経過時間または経過時間とカウンターの組み合わせとして解釈します(したがって、メトリクス推定値には、最後の M 測定値と最後の T 秒からのおおよそのコントリビュートが含まれます)。
メトリクスファクトリ
MessageChannel インスタンスおよび MessageHandler インスタンスにカスタムチャネルメトリクスを提供できるように、戦略インターフェース MetricsFactory が導入されました。デフォルトでは、DefaultMetricsFactory は MessageChannelMetrics と MessageHandlerMetrics のデフォルト実装を提供し、先に説明しました。デフォルトの MetricsFactory をオーバーライドするには、MetricsFactory Bean インスタンスへの参照を提供して、前述のように構成します。次のセクションで説明するように、デフォルトの実装をカスタマイズするか、AbstractMessageChannelMetrics または AbstractMessageHandlerMetrics を継承してまったく異なる実装を提供できます。
Micrometer 統合も参照してください。
前述のデフォルトのメトリクスファクトリに加えて、フレームワークは AggregatingMetricsFactory を提供します。このファクトリは、AggregatingMessageChannelMetrics および AggregatingMessageHandlerMetrics インスタンスを作成します。非常に大容量のシナリオでは、統計をキャプチャーするコストが非常に高くなる可能性があります(システムに 2 回呼び出して、各メッセージのデータを保存する時間)。集約メトリクスは、メッセージのサンプル全体のレスポンス時間を集約します。これにより、CPU 時間を大幅に節約できます。
| メッセージがバーストで到着した場合、統計が歪む可能性があります。これらのメトリクスは、高一定のメッセージレートで使用することを目的としています。 |
次の例は、集約メトリクスファクトリを定義する方法を示しています。
<bean id="aggregatingMetricsFactory"
class="org.springframework.integration.support.management.AggregatingMetricsFactory">
<constructor-arg value="1000" /> <!-- sample size -->
</bean>上記の構成では、1000 メッセージを超える期間が集約されます。カウント(送信およびエラー)はメッセージごとに維持されますが、統計はメッセージ 1000 個ごとです。
デフォルトのチャネルおよびハンドラー統計のカスタマイズ
これらの値の詳細については、ExponentialMovingAverage* クラスの時間ベースの平均推定および Javadoc を参照してください。
デフォルトでは、DefaultMessageChannelMetrics および DefaultMessageHandlerMetrics は、10 回の測定の「ウィンドウ」、1 秒のレート期間(1 秒あたりの平均レート)、1 分の減衰経過期間を使用します。
これらのデフォルトをオーバーライドする場合は、適切に構成されたメトリクスを返すカスタム MetricsFactory を提供し、前述のように MBean エクスポーターでそれへの参照を提供できます。
次の例は、その方法を示しています。
public static class CustomMetrics implements MetricsFactory {
@Override
public AbstractMessageChannelMetrics createChannelMetrics(String name) {
return new DefaultMessageChannelMetrics(name,
new ExponentialMovingAverage(20, 1000000.),
new ExponentialMovingAverageRate(2000, 120000, 30, true),
new ExponentialMovingAverageRatio(130000, 40, true),
new ExponentialMovingAverageRate(3000, 140000, 50, true));
}
@Override
public AbstractMessageHandlerMetrics createHandlerMetrics(String name) {
return new DefaultMessageHandlerMetrics(name, new ExponentialMovingAverage(20, 1000000.));
}
}高度なカスタマイズ
前述のカスタマイズは大規模であり、MBean エクスポーターによってエクスポートされるすべての適切な Bean に適用されます。これは、XML 構成を使用するときに利用できるカスタマイズの範囲です。
AbstractMessageChannel および AbstractMessageHandler で configureMetrics メソッドを呼び出すことにより、Java @Configuration を使用して、または実行時にプログラムで(アプリケーションコンテキストがリフレッシュされた後)個別の Bean に異なる実装を提供できます。
パフォーマンスの改善
以前は、時間ベースのメトリクス(時間ベースの平均推定を参照)はリアルタイムで計算されていました。代わりに、取得時に統計が計算されるようになりました。これにより、統計ごとに少量のメモリが追加されますが、パフォーマンスが大幅に向上しました。前述のように、Lifecycle メソッドの呼び出しを許可する MBean を保持したまま、統計を完全に無効にすることができます。
JMX サポート
Spring Integration は、JMX 通知を受信および公開するためのチャネルアダプターを提供します。
この依存関係をプロジェクトに含める必要があります。
受信チャネルアダプターは JMX MBean 属性値のポーリングを許可し、発信チャネルアダプターは JMX MBean 操作の呼び出しを許可します。
通知リスニングチャネルアダプター
通知リスニングチャネルアダプターには、このリスナーを登録する通知を発行する MBean の JMX ObjectName が必要です。非常に単純な構成は、次のようになります。
<int-jmx:notification-listening-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"/>notification-listening-channel-adapter は起動時に MBeanServer に登録され、デフォルトの Bean 名は mbeanServer です。これは、Spring の <context:mbean-server/> 要素を使用したときに生成される Bean 名と同じです。別の名前を使用する必要がある場合は、mbean-server 属性を必ず含めてください。 |
アダプターは、NotificationFilter および「ハンドバック」オブジェクトへの参照を受け入れて、各通知で戻されるコンテキストを提供することもできます。これらの属性は両方ともオプションです。上記の例を拡張して、これらの属性と明示的な MBeanServer Bean 名を含めると、次の例が生成されます。
<int-jmx:notification-listening-channel-adapter id="adapter"
channel="channel"
mbean-server="someServer"
object-name="example.domain:name=somePublisher"
notification-filter="notificationFilter"
handback="myHandback"/>_Notification-listening チャネルアダプターはイベント駆動型であり、MBeanServer に直接登録されます。ポーラー構成は必要ありません。
このコンポーネントの場合のみ、 DEBUG レベルのロギングが有効になっている場合、検出された MBean の名前が記録されます。 |
通知発行チャネルアダプター
通知発行チャネルアダプターは比較的単純です。次の例に示すように、構成に必要なのは JMX オブジェクト名のみです。
<context:mbean-export/>
<int-jmx:notification-publishing-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"/> また、MBeanExporter がコンテキストに存在する必要があります。そのため、前の例で <context:mbean-export/> 要素も示されています。
このアダプターのチャネルにメッセージが送信されると、メッセージのコンテンツから通知が作成されます。ペイロードが String である場合、通知の message テキストとして渡されます。その他のペイロード型は、通知の userData として渡されます。
JMX 通知には type もあり、ドット区切りの String である必要があります。type を提供するには 2 つの方法があります。JmxHeaders.NOTIFICATION_TYPE キーに関連付けられたメッセージヘッダー値には常に優先順位が与えられます。または、次の例に示すように、構成でフォールバック default-notification-type 属性を提供できます。
<context:mbean-export/>
<int-jmx:notification-publishing-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"
default-notification-type="some.default.type"/>属性ポーリングチャネルアダプター
属性ポーリングチャネルアダプターは、MBean を介して管理属性として使用可能な値を定期的に確認する必要がある場合に役立ちます。Spring Integration の他のポーリングアダプターと同じ方法でポーラーを構成できます(またはデフォルトのポーラーを使用できます)。object-name と attribute-name が必要です。MBeanServer の参照も必要です。ただし、デフォルトでは、それが自動的に mbeanServer という名前 Bean ためのチェックは、通知リスニングチャネルアダプターと同じでは先に述べました。次の例は、属性ポーリングチャネルアダプターを XML で構成する方法を示しています。
<int-jmx:attribute-polling-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=someService"
attribute-name="InvocationCount">
<int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:attribute-polling-channel-adapter>ツリーポーリングチャネルアダプター
ツリーポーリングチャネルアダプターは、JMX MBean ツリーにクエリを実行し、クエリに一致するオブジェクトのグラフであるペイロードを含むメッセージを送信します。デフォルトでは、MBean はプリミティブと、Map、List、配列などの単純なオブジェクトにマップされます。そうすることで、(たとえば)JSON への単純な変換が可能になります。MBeanServer 参照も必要です。ただし、デフォルトでは、それが自動的に mbeanServer という名前 Bean ためのチェックは、通知リスニングチャネルアダプターと同じでは先に述べました。次の例は、XML を使用してツリーポーリングチャネルアダプターを設定する方法を示しています。
<int-jmx:tree-polling-channel-adapter id="adapter"
channel="channel"
query-name="example.domain:type=*">
<int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:tree-polling-channel-adapter> 上記の例には、選択した MBean のすべての属性が含まれています。適切なフィルターが構成された MBeanObjectConverter を提供することにより、属性をフィルターに掛けることができます。converter 属性を使用して Bean 定義への参照としてコンバーターを提供するか、内部 <bean/> 定義を使用できます。Spring Integration は、コンストラクター引数で MBeanAttributeFilter を取ることができる DefaultMBeanObjectConverter を提供します。
Spring Integration は 2 つの標準フィルターを提供します。NamedFieldsMBeanAttributeFilter では、含める属性のリストを指定できます。NotNamedFieldsMBeanAttributeFilter では、除外する属性のリストを指定できます。独自のフィルターを実装することもできます。
操作呼び出しチャネルアダプター
操作呼び出しチャネルアダプターを使用すると、MBean によって公開されるすべての管理操作のメッセージ駆動型呼び出しが可能になります。各呼び出しには、呼び出される操作名とターゲット MBean のオブジェクト名が必要です。これらは両方とも、アダプター構成または JmxHeaders.OBJECT_NAME および JmxHeaders.OPERATION_NAME メッセージヘッダーを介してそれぞれ明示的に提供する必要があります。
<int-jmx:operation-invoking-channel-adapter id="adapter"
object-name="example.domain:name=TestBean"
operation-name="ping"/> その場合、アダプターは mbeanServer Bean を検出できる必要があるだけです。別の Bean 名が必要な場合は、mbean-server 属性に参照を提供します。
メッセージのペイロードは、操作のパラメーター(存在する場合)にマップされます。String キーを持つ Map -typed ペイロードは名前 / 値のペアとして扱われますが、List または配列は単純な引数リストとして渡されます(明示的なパラメーター名はありません)。操作に単一のパラメーター値が必要な場合、ペイロードはその単一の値を表すことができます。また、操作にパラメーターが必要ない場合、ペイロードは無視されます。
ヘッダーを含む必要のないメッセージによって呼び出される単一の共通操作のチャネルを公開する場合、その最後のオプションはうまく機能します。
操作呼び出し送信ゲートウェイ
操作を呼び出すチャネルアダプターと同様に、Spring Integration は操作を呼び出す送信ゲートウェイも提供します。これは、戻り値が必要な場合に非 void 操作を処理するときに使用できます。戻り値は、メッセージペイロードとしてゲートウェイによって指定された reply-channel に送信されます。次の例は、XML を使用して操作呼び出し発信ゲートウェイを構成する方法を示しています。
<int-jmx:operation-invoking-outbound-gateway request-channel="requestChannel"
reply-channel="replyChannel"
object-name="o.s.i.jmx.config:type=TestBean,name=testBeanGateway"
operation-name="testWithReturn"/>reply-channel 属性を指定しない場合、応答メッセージは IntegrationMessageHeaderAccessor.REPLY_CHANNEL ヘッダーで識別されるチャネルに送信されます。通常、このヘッダーは、ゲートウェイコンポーネントなどのメッセージフローへのエントリポイントによって自動作成されます。ただし、Spring Integration メッセージを手動で作成してチャネルに直接送信することによってメッセージフローが開始された場合、メッセージヘッダーを明示的に指定するか、reply-channel 属性を使用する必要があります。
MBean エクスポーター
Spring Integration コンポーネントは、IntegrationMBeanExporter の構成時に MBean として公開される場合があります。IntegrationMBeanExporter のインスタンスを作成するには、Bean を定義し、MBeanServer への参照とドメイン名(必要な場合)を提供します。ドメインを除外できます。この場合、デフォルトのドメインは org.springframework.integration です。次の例は、IntegrationMBeanExporter および関連する MBeanServer インスタンスのインスタンスを宣言する方法を示しています。
<int-jmx:mbean-export id="integrationMBeanExporter"
default-domain="my.company.domain" server="mbeanServer"/>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>MBean エクスポーターは、Spring コアで提供されるものと直交しています。メッセージチャネルとメッセージハンドラーを登録しますが、それ自体は登録しません。標準の 正常なシャットダウン管理操作で説明したように、便利な操作もあります。 |
Spring Integration 4.0 は、@Configuration クラスレベルでいくつかの便利なオプションを備えた型 IntegrationMBeanExporter のデフォルト integrationMbeanExporter Bean の便利な設定を可能にする @EnableIntegrationMBeanExport アノテーションを導入しました。次の例は、この Bean を構成する方法を示しています。
@Configuration
@EnableIntegration
@EnableIntegrationMBeanExport(server = "mbeanServer", managedComponents = "input")
public class ContextConfiguration {
@Bean
public MBeanServerFactoryBean mbeanServer() {
return new MBeanServerFactoryBean();
}
} より多くのオプションを提供したり、複数の IntegrationMBeanExporter Bean が必要な場合(異なる MBean サーバー用、または @EnableMBeanExport などを介して標準 Spring MBeanExporter との競合を避けるため)、IntegrationMBeanExporter を汎用 Bean として構成できます。
MBean オブジェクト名
アプリケーション内のすべての MessageChannel、MessageHandler、MessageSource インスタンスは、管理および監視機能を提供するために MBean エクスポーターによってラップされます。各コンポーネント型に対して生成された JMX オブジェクト名を次の表に示します。
| コンポーネントタイプ | オブジェクト名 |
|---|---|
MessageChannel | `o.s.i:type=MessageChannel,name=<channelName>` |
MessageSource | `o.s.i:type=MessageSource,name=<channelName>,bean=<source>` |
MessageHandler | `o.s.i:type=MessageSource,name=<channelName>,bean=<source>` |
ソースおよびハンドラーのオブジェクト名の bean 属性は、次の表のいずれかの値を取ります。
| Bean 値 | 説明 |
|---|---|
endpoint | 囲んでいるエンドポイントの Bean 名(例: |
anonymous | 囲んでいるエンドポイントにユーザー指定の Bean 名がなかったことを示すため、JMX 名は入力チャネル名です。 |
internal | よく知られている Spring Integration のデフォルトコンポーネント |
ハンドラー / ソース | 上記のどれでもない。監視されているオブジェクトの |
object-name-static-properties 属性で Properties オブジェクトへの参照を提供することにより、オブジェクト名にカスタム要素を追加できます。
また、Spring Integration 3.0 以降、object-naming-strategy 属性を設定することにより、カスタム ObjectNamingStrategy (Javadoc) を使用できます。そうすることで、すべての統合 MBean を「統合」型にグループ化するなど、MBean の命名をより詳細に制御できます。次の例は、1 つの可能なカスタム命名戦略の実装を示しています。
public class Namer implements ObjectNamingStrategy {
private final ObjectNamingStrategy realNamer = new KeyNamingStrategy();
@Override
public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
String actualBeanKey = beanKey.replace("type=", "type=Integration,componentType=");
return realNamer.getObjectName(managedBean, actualBeanKey);
}
}beanKey 引数は String であり、default-domain で始まり、追加の静的プロパティを含む標準オブジェクト名が含まれています。前の例では、標準の type パーツを componentType に移動し、type を「統合」に設定して、1 つのクエリですべての統合 MBean を選択できるようにします: `my.domain:type=Integration,*`。そうすることで、VisualVM などのツールのドメインにある 1 つのツリーエントリに Bean をグループ化することもできます。
デフォルトの命名戦略は MetadataNamingStrategy (Javadoc) です。エクスポーターは、default-domain をそのオブジェクトに伝搬して、Bean キーの解析が失敗した場合にフォールバックオブジェクト名を生成できるようにします。カスタム命名戦略が MetadataNamingStrategy (またはそのサブクラス)の場合、エクスポーターは default-domain を伝搬しません。戦略 Bean で設定する必要があります。 |
バージョン 5.1 以降。Java 識別子(またはピリオド .)で許可されていない文字が含まれている場合、Bean 名(オブジェクト名の name キーで表される)は引用されます。
JMX の改善
バージョン 4.2 はいくつかの重要な改善を導入し、フレームワークでの JMX サポートのかなり大きなオーバーホールを表します。これらにより、JMX 統計収集のパフォーマンスが大幅に向上し、その制御が大幅に向上しました。ただし、いくつかの特定の(珍しい)状況では、ユーザーコードにいくつかの影響があります。これらの変更の詳細を以下に示しますが、必要な場合は注意してください。
- メトリクスキャプチャー
以前は、
MessageSource、MessageChannel、MessageHandlerメトリクスは、オブジェクトを JDK 動的プロキシでラップして、適切なメソッド呼び出しをインターセプトし、統計をキャプチャーすることによってキャプチャーされていました。プロキシは、統合 MBean エクスポータがコンテキストで宣言されたときに追加されました。現在、統計は Bean 自体によってキャプチャーされます。詳細については、指標と管理を参照してください。
この変更は、カスタムハンドラーが AbstractMessageHandlerを継承しない限り、カスタムMessageHandler実装の MBean または統計を自動的に取得しないことを意味します。これを解決する最も簡単な方法は、AbstractMessageHandlerを継承することです。それができない場合、別の回避策は、MessageHandlerMetricsインターフェースを実装することです。便宜上、DefaultMessageHandlerMetricsが提供され、統計をキャプチャーおよびレポートします。beforeHandleおよびafterHandleを適切なタイミングで呼び出す必要があります。MessageHandlerMetricsメソッドは、このオブジェクトに委譲して、各統計を取得できます。同様に、MessageSource実装はAbstractMessageSourceを継承するか、MessageSourceMetricsを実装する必要があります。メッセージソースはカウントのみをキャプチャーするため、便利なクラスは提供されていません。AtomicLongフィールドでカウントを維持する必要があります。プロキシを削除すると、さらに 2 つの利点があります。
プロキシがスタック上にないため、例外のスタックトレースが減少します(JMX が有効な場合)。
同じ Bean に対して 2 つの MBean がエクスポートされた場合、属性と操作が統合された単一の MBean のみがエクスポートされるようになりました(MBean 統合箇条書きを参照)。
- レゾリューション
(
System.currentTimeMillis()ではなく)System.nanoTime()が、時間をキャプチャーするために使用されるようになりました。これにより、特に 1 ミリ秒未満の継続時間が予想される場合に、一部の JVM でより正確になります。- 初期統計収集状態の設定
以前は、JMX を有効にすると、すべてのソース、チャネル、ハンドラーが統計をキャプチャーしました。個々のコンポーネントで統計を有効にするかどうかを制御できるようになりました。さらに、完全な時間ベースの統計をキャプチャーする代わりに、
MessageChannelインスタンスとMessageHandlerインスタンスで単純なカウントをキャプチャーできます。これは、詳細な統計が必要な場所を選択的に構成し、実行時に収集を有効または無効にすることができるため、パフォーマンスに大きな影響を与える可能性があります。指標と管理を参照してください。
- @IntegrationManagedResource
@ManagedResourceアノテーションと同様に、@IntegrationManagedResourceはクラスを MBean としてエクスポートする資格があるものとしてマークします。ただし、アプリケーションコンテキストにIntegrationMBeanExporterがある場合にのみエクスポートされます。以前に `@ManagedResource` でアノテーションが付けられていた特定の Spring Integration クラス(
org.springframework.integration内)パッケージには、@ManagedResourceと@IntegrationManagedResourceの両方でアノテーションが付けられるようになりました。これは下位互換性のためです(次の項目を参照)。このような MBean は、任意のコンテキストMBeanServerまたはIntegrationMBeanExporterによってエクスポートされます(両方ではありません。両方のエクスポーターが存在する場合、Bean がmanaged-componentsパターンと一致すると、Bean は統合エクスポーターによってエクスポートされます)。- 統合された MBean
フレームワーク内の特定のクラス(マッピングルーターなど)には、メトリクスと
Lifecycleによって提供される属性と操作に加えて、追加の属性と操作があります。ここでは、例としてRouterを使用します。以前は、これらの型の Bean は 2 つの別個の MBean としてエクスポートされていました。
メトリクス MBean(
intDomain:type=MessageHandler,name=myRouter,bean=endpointなどのオブジェクト名を持つ)。この MBean には、メトリクス属性とメトリクス / ライフサイクル操作がありました。2 番目の MBean(
ctxDomain:name=org.springframework.integration.config.RouterFactoryBean#0、type = MethodInvokingRouter` などのオブジェクト名)が、チャネルマッピング属性と操作とともにエクスポートされました。これで、属性と操作が単一の MBean に統合されました。オブジェクト名はエクスポータによって異なります。統合 MBean エクスポーターによってエクスポートされる場合、オブジェクト名は、例:
intDomain:type=MessageHandler,name=myRouter,bean=endpointです。別のエクスポーターによってエクスポートされた場合、オブジェクト名は次のようになります。例:ctxDomain:name=org.springframework.integration.config.RouterFactoryBean#0,type=MethodInvokingRouter。統合エクスポータ以外のエクスポータによって統計が有効にされていない(属性は0である)ことを除いて、これらの MBean(オブジェクト名を除く)の間に違いはありません。JMX 操作を使用して、実行時に統計を有効にできます。統合 MBean エクスポーターによってエクスポートされる場合、初期状態は前述のように管理できます。現在 2 番目の MBean を使用して、たとえばチャネルマッピングを変更し、統合 MBean エクスポーターを使用している場合、MBean の統合によりオブジェクト名が変更されていることに注意してください。統合 MBean エクスポーターを使用していない場合、変更はありません。
- MBean エクスポーター Bean の名前パターン
以前は、
managed-componentsパターンは包括的のみでした。Bean 名がパターンの 1 つと一致した場合、その名前が含まれます。これで、パターンの前に!を付けることで、パターンを無効にすることができます。例:!thing*, thingsは、thingsを除き、thingで始まらないすべての Bean 名に一致します。パターンは左から右に評価されます。最初の一致(正または負)が勝ち、それ以降のパターンは適用されません。この構文をパターンに追加すると、1 つの可能性のある(おそらくありそうもない)問題が発生します。 "!thing"という名前の Bean があり、MBean エクスポーターのmanaged-componentsパターンに!thingのパターンを含めた場合、一致しなくなります。パターンはthingという名前ではないすべての Bean に一致するようになりました。この場合、\を使用して、パターン内の!をエスケープできます。\!thingパターンは、!thingという名前の Bean と一致します。- IntegrationMBeanExporter の変更
IntegrationMBeanExporterはSmartLifecycleを実装しなくなりました。これは、MBean の登録および登録解除にstart()およびstop()操作が使用できなくなったことを意味します。MBean は、コンテキストの初期化中に登録され、コンテキストが破棄されると登録解除されます。
正常なシャットダウン管理操作
MBean エクスポーターは、JVM を終了する前に使用することを目的とした、秩序正しい方法でアプリケーションをシャットダウンする JMX 操作を提供します。次の例は、その使用方法を示しています。
public void stopActiveComponents(long howLong)その使用と操作は正常なシャットダウンで説明されています。
メッセージ履歴
メッセージングアーキテクチャの主な利点は、参加しているコンポーネントが相互の認識を維持できないように、疎結合です。この事実だけで、アプリケーションは非常に柔軟になり、残りのフローに影響を与えずにコンポーネントを変更したり、メッセージングルートを変更したり、メッセージ消費スタイルを変更したりできます(ポーリングとイベントドリブン)。しかし、この控えめなスタイルのアーキテクチャは、物事がうまくいかない場合には難しいことがわかります。デバッグするときは、おそらくメッセージに関する情報(その発信元、通過したチャネル、その他の詳細)をできるだけ多く取得する必要があります。
メッセージ履歴は、デバッグまたは監査証跡を維持するために、メッセージパスの認識レベルを維持するオプションを提供することで役立つパターンの 1 つです。Spring 統合は、メッセージにヘッダーを追加し、メッセージが追跡対象コンポーネントを通過するたびにそのヘッダーを更新することにより、メッセージフローを設定してメッセージ履歴を維持する簡単な方法を提供します。
メッセージ履歴の構成
メッセージ履歴を有効にするには、次の例に示すように、構成で message-history 要素のみを定義する必要があります。
<int:message-history/> これで、すべての名前付きコンポーネント( "id" が定義されているコンポーネント)が追跡されます。フレームワークは、メッセージに "history" ヘッダーを設定します。その値は List<Properties> です。
次の構成例を検討してください。
<int:gateway id="sampleGateway"
service-interface="org.springframework.integration.history.sample.SampleGateway"
default-request-channel="bridgeInChannel"/>
<int:chain id="sampleChain" input-channel="chainChannel" output-channel="filterChannel">
<int:header-enricher>
<int:header name="baz" value="baz"/>
</int:header-enricher>
</int:chain>上記の構成により、単純なメッセージ履歴構造が生成され、出力は次のようになります。
[{name=sampleGateway, type=gateway, timestamp=1283281668091},
{name=sampleChain, type=chain, timestamp=1283281668094}] メッセージ履歴にアクセスするには、MessageHistory ヘッダーにアクセスするだけで済みます。次の例は、その方法を示しています。
Iterator<Properties> historyIterator =
message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
assertTrue(historyIterator.hasNext());
Properties gatewayHistory = historyIterator.next();
assertEquals("sampleGateway", gatewayHistory.get("name"));
assertTrue(historyIterator.hasNext());
Properties chainHistory = historyIterator.next();
assertEquals("sampleChain", chainHistory.get("name")); すべてのコンポーネントを追跡したくない場合があります。名前に基づいて特定のコンポーネントに履歴を制限するには、tracked-components 属性を指定し、追跡するコンポーネントに一致するコンポーネント名とパターンのコンマ区切りリストを指定できます。次の例は、その方法を示しています。
<int:message-history tracked-components="*Gateway, sample*, aName"/>前の例では、'Gateway' で終わる、'sample' で始まる、または名前 'aName' と完全に一致するコンポーネントに対してのみ、メッセージ履歴が保持されます。
バージョン 4.0 から、@Configuration クラスで @EnableMessageHistory アノテーションを使用することもできます。さらに、MessageHistoryConfigurer Bean は IntegrationMBeanExporter (MBean エクスポーターを参照)によって JMX MBean として公開され、実行時にパターンを変更できるようになりました。ただし、パターンを変更するには、Bean を停止する(メッセージ履歴をオフにする)必要があることに注意してください。この機能は、一時的に履歴をオンにしてシステムを分析するのに役立つ場合があります。MBean のオブジェクト名は <domain>:name=messageHistoryConfigurer,type=MessageHistoryConfigurer です。
複数の Bean(@EnableMessageHistory および <message-history/> によって宣言されている)が存在する場合、すべて同じコンポーネント名パターンを持っている必要があります(トリミングおよびソート時)。MessageHistoryConfigurer に汎用 <bean/> 定義を使用しないでください。 |
| 定義により、メッセージ履歴ヘッダーは不変です(履歴を書き換えることはできません)。メッセージ履歴値を書き込むとき、コンポーネントは新しいメッセージを作成するか(コンポーネントがオリジンの場合)、リクエストメッセージから履歴をコピーし、それを変更して応答メッセージに新しいリストを設定します。どちらの場合でも、メッセージ自体がスレッドの境界を越えている場合でも、値を追加できます。つまり、履歴値により、非同期メッセージフローのデバッグが大幅に簡素化されます。 |
メッセージストア
エンタープライズ統合パターン (英語) (EIP)ブックは、メッセージをバッファリングする機能を持ついくつかのパターンを識別します。例: アグリゲーターは、解放できるまでメッセージをバッファリングし、QueueChannel は、コンシューマーがそのチャネルからメッセージを明示的に受信するまでメッセージをバッファリングします。メッセージフロー内の任意の時点で発生する可能性がある障害のため、メッセージをバッファリングする EIP コンポーネントは、メッセージが失われる可能性のあるポイントも導入します。
メッセージを失うリスクを軽減するために、EIP はメッセージストア (英語) パターンを定義します。これにより、EIP コンポーネントは通常、ある種の永続ストア(RDBMS など)にメッセージを保存 (英語) できます。
Spring Integration は、以下によってメッセージストアパターンのサポートを提供します。
org.springframework.integration.store.MessageStore戦略インターフェースの定義このインターフェースのいくつかの実装を提供する
MessageStoreインターフェースを実装するインスタンスを挿入できるように、メッセージをバッファリングする機能を持つすべてのコンポーネントでmessage-store属性を公開します。
特定のメッセージストア実装の設定方法と特定のバッファリングコンポーネントへの MessageStore 実装の注入方法の詳細は、マニュアル全体で説明されています(QueueChannel、アグリゲーター、遅延器などの特定のコンポーネントを参照)。次の例のペアは、QueueChannel およびアグリゲーターのメッセージストアへの参照を追加する方法を示しています。
<int:channel id="myQueueChannel">
<int:queue message-store="refToMessageStore"/>
<int:channel><int:aggregator … message-store="refToMessageStore"/> デフォルトでは、メッセージは MessageStore の実装である o.s.i.store.SimpleMessageStore を使用してメモリに保存されます。これは、非永続メッセージの潜在的な損失が懸念されない開発環境または単純な低ボリューム環境では問題ない場合があります。ただし、一般的な本番アプリケーションには、メッセージ損失のリスクを軽減するだけでなく、潜在的なメモリ不足エラーを回避するために、より堅牢なオプションが必要です。そのため、さまざまなデータストア用の MessageStore 実装も提供しています。以下は、サポートされている実装の完全なリストです。
JDBC メッセージストア : RDBMS を使用してメッセージを保存する
Redis メッセージストア : Redis キー / 値データストアを使用してメッセージを保存する
MongoDB メッセージストア : MongoDB ドキュメントストアを使用してメッセージを保存する
Gemfire メッセージストア : Gemfire 分散キャッシュを使用してメッセージを保存します
ただし、 メッセージデータ(ペイロードとヘッダー)は、 特定の型のデータを表すヘッダーに特に注意してください。例: ヘッダーの 1 つに Spring Bean のインスタンスが含まれている場合、逆直列化すると、その Bean の別のインスタンスになり、フレームワークによって作成された暗黙的なヘッダーの一部( Spring Integration バージョン 3.0 から、 また、次のようにメッセージフローを構成するときに何が起こるかを考慮してください: ゲートウェイ→キューチャネル(永続的なメッセージストアによってバッキング)→サービスアクティベーター。そのゲートウェイは一時的な応答チャネルを作成しますが、サービスアクティベーターのポーラーがキューから読み取るまでに失われます。この場合も、ヘッダーエンリッチャーを使用して、ヘッダーを 詳しくは、ヘッダーエンリッチャーを参照してください。 |
Spring Integration 4.0 は 2 つの新しいインターフェースを導入しました:
ChannelMessageStore:QueueChannelインスタンスに固有の操作を実装するにはPriorityCapableChannelMessageStore:PriorityChannelインスタンスに使用されるMessageStore実装をマークし、持続メッセージの優先順位を提供するため。
実際の動作は実装によって異なります。このフレームワークは、QueueChannel および PriorityChannel の永続的な MessageStore として使用できる次の実装を提供します。
SimpleMessageStore に関する注意 バージョン 4.1 以降、 アグリゲーターなどのコンポーネントの外部のグループストアにアクセスするユーザーは、コピーの代わりにアグリゲーターが使用しているグループへの直接参照を取得するようになりました。アグリゲーターの外部でグループを操作すると、予測できない結果が生じる可能性があります。 このため、このような操作を実行しないか、 |
MessageGroupFactory を使用する
バージョン 4.3 から、MessageGroupStore 実装の一部にカスタム MessageGroupFactory 戦略を注入して、MessageGroupStore が使用する MessageGroup インスタンスを作成およびカスタマイズできます。これはデフォルトで SimpleMessageGroupFactory になり、GroupType.HASH_SET (LinkedHashSet)内部コレクションに基づいて SimpleMessageGroup インスタンスを生成します。他の可能なオプションは SYNCHRONISED_SET および BLOCKING_QUEUE です。最後のオプションを使用して、以前の SimpleMessageGroup の動作を復元できます。PERSISTENT オプションも利用できます。詳細については、次のセクションを参照してください。バージョン 5.0.1 から、LIST オプションは、グループ内のメッセージの順序と一意性が重要でない場合にも使用できます。
永続的な MessageGroupStore および遅延ロード
バージョン 4.3 以降、すべての永続的な MessageGroupStore インスタンスは、遅延ロード方式でストアから MessageGroup インスタンスとその messages を取得します。ほとんどの場合、各相関操作でストアから MessageGroup 全体をロードするオーバーヘッドを追加する場合、相関 MessageHandler インスタンス(アグリゲーターおよびリシーケンサーを参照)に役立ちます。
AbstractMessageGroupStore.setLazyLoadMessageGroups(false) オプションを使用して、構成から遅延ロード動作をオフに切り替えることができます。
MongoDB MessageStore (MongoDB メッセージストア)および <aggregator> (アグリゲーター)での遅延ロードのパフォーマンステストでは、次のようなカスタム release-strategy を使用します。
<int:aggregator input-channel="inputChannel"
output-channel="outputChannel"
message-store="mongoStore"
release-strategy-expression="size() == 1000"/>1000 個の単純なメッセージに対して、次のような結果が生成されます。
...
StopWatch 'Lazy-Load Performance': running time (millis) = 38918
-----------------------------------------
ms % Task name
-----------------------------------------
02652 007% Lazy-Load
36266 093% Eager
...メタデータストア
多くの外部システム、サービス、リソースはトランザクション対応ではなく(Twitter、RSS、ファイルシステムなど)、データを既読としてマークする機能はありません。また、場合によっては、一部の統合ソリューションにエンタープライズ統合パターンべき等レシーバー (英語) を実装する必要があります。このゴールを達成し、外部システムとの次の対話の前にエンドポイントの以前の状態を保存するため、または次のメッセージを処理するために、Spring Integration は、一般的なキーと値の契約を持つ org.springframework.integration.metadata.MetadataStore インターフェースの実装としてメタデータストアコンポーネントを提供します。
メタデータストアは、さまざまな種類の汎用メタデータ(たとえば、処理された最後のフィードエントリの公開日)を格納して、フィードアダプターなどのコンポーネントが重複を処理できるように設計されています。コンポーネントに MetadataStore への参照が直接提供されない場合、メタデータストアを見つけるためのアルゴリズムは次のとおりです。最初に、アプリケーションコンテキストで metadataStore ID を持つ Bean を探します。見つかった場合は、それを使用します。そうでない場合は、SimpleMetadataStore の新しいインスタンスを作成します。これは、現在実行中のアプリケーションコンテキストのライフサイクル内でメタデータのみを永続化するメモリ内実装です。つまり、再起動すると、エントリが重複する可能性があります。
アプリケーションコンテキストの再起動間でメタデータを保持する必要がある場合、フレームワークは次の永続的な MetadataStores を提供します。
PropertiesPersistingMetadataStore
PropertiesPersistingMetadataStore は、プロパティファイルと PropertiesPersister (Javadoc) によってサポートされています。
デフォルトでは、アプリケーションコンテキストが正常に閉じられたときの状態のみを保持します。Flushable を実装しているため、flush() を呼び出すことで、状態を自由に維持できます。次の例は、XML で "PropertiesPersistingMetadataStore" を構成する方法を示しています。
<bean id="metadataStore"
class="org.springframework.integration.metadata.PropertiesPersistingMetadataStore"/> または、MetadataStore インターフェースの独自の実装(たとえば JdbcMetadataStore)を提供し、それをアプリケーションコンテキストで Bean として構成できます。
バージョン 4.0 以降、SimpleMetadataStore、PropertiesPersistingMetadataStore、RedisMetadataStore は ConcurrentMetadataStore を実装します。これらはアトミックアップデートを提供し、複数のコンポーネントまたはアプリケーションインスタンスで使用できます。
べき等レシーバーとメタデータストア
メタデータストアは、受信メッセージがすでに処理されており、破棄するか、破棄時に他のロジックを実行できる場合、受信メッセージをフィルターする必要がある場合に、EIP べき等レシーバー (英語) パターンを実装できます。次の構成は、その方法の例を示しています。
<int:filter input-channel="serviceChannel"
output-channel="idempotentServiceChannel"
discard-channel="discardChannel"
expression="@metadataStore.get(headers.businessKey) == null"/>
<int:publish-subscribe-channel id="idempotentServiceChannel"/>
<int:outbound-channel-adapter channel="idempotentServiceChannel"
expression="@metadataStore.put(headers.businessKey, '')"/>
<int:service-activator input-channel="idempotentServiceChannel" ref="service"/> べき等エントリの value は有効期限になる可能性があり、その後、そのエントリは何らかのスケジュールされたリーパーによってメタデータストアから削除される必要があります。
べき等レシーバーエンタープライズ統合パターンも参照してください。
MetadataStoreListener
次の例に示すように、一部のメタデータストア(現在は zookeeper のみ)は、アイテムの変更時にイベントを受信するリスナーの登録をサポートしています。
public interface MetadataStoreListener {
void onAdd(String key, String value);
void onRemove(String key, String oldValue);
void onUpdate(String key, String newValue);
} 詳細については、Javadoc を参照してください。イベントのサブセットのみに関心がある場合は、MetadataStoreListenerAdapter をサブクラス化できます。
制御バス
エンタープライズ統合パターン (英語) (EIP)ブックに従って、コントロールバスの背景となる考え方は、「アプリケーションレベル」メッセージングに使用されるのと同じメッセージングシステムをフレームワーク内のコンポーネントの監視と管理に使用できるということです。Spring Integration では、公開された操作を呼び出す手段としてメッセージを送信できるように、上記のアダプターに基づいて構築しています。
次の例は、XML で制御バスを構成する方法を示しています。
<int:control-bus input-channel="operationChannel"/>制御バスには、アプリケーションコンテキストで Bean の操作を呼び出すためにアクセスできる入力チャネルがあります。また、エンドポイントをアクティブにするサービスのすべての共通プロパティもあります。例: 操作の結果に、ダウンストリームチャネルに送信する戻り値がある場合、出力チャネルを指定できます。
制御バスは、Spring Expression Language(SpEL)式として入力チャネルでメッセージを実行します。メッセージを受け取り、本文を式にコンパイルし、コンテキストを追加してから実行します。デフォルトのコンテキストは、@ManagedAttribute または @ManagedOperation でアノテーションが付けられたメソッドをサポートします。また、Spring の Lifecycle インターフェース(およびバージョン 5.2 以降の Pausable 拡張)のメソッドをサポートし、Spring の TaskExecutor および TaskScheduler 実装のいくつかを構成するために使用されるメソッドをサポートします。制御バスで独自のメソッドを使用できるようにする最も簡単な方法は、@ManagedAttribute または @ManagedOperation アノテーションを使用することです。これらのアノテーションは、メソッドを JMX MBean レジストリに公開するためにも使用されるため、便利な副産物を提供します。多くの場合、コントロールバスに公開するのと同じ型の操作は、JMX を介して公開するのに適しています。アプリケーションコンテキスト内の特定のインスタンスの解決は、一般的な SpEL 構文で実現されます。これを行うには、Bean の SpEL 接頭辞(@)を Bean 名に指定します。例: Spring Bean でメソッドを実行するために、クライアントは次のように操作チャネルにメッセージを送信できます。
Message operation = MessageBuilder.withPayload("@myServiceBean.shutdown()").build();
operationChannel.send(operation) 式のコンテキストのルートは Message 自体であるため、式内の変数として payload および headers にもアクセスできます。これは、Spring Integration エンドポイントの他のすべての式サポートと一致しています。
Java アノテーションを使用すると、コントロールバスを次のように構成できます。
@Bean
@ServiceActivator(inputChannel = "operationChannel")
public ExpressionControlBusFactoryBean controlBus() {
return new ExpressionControlBusFactoryBean();
}同様に、Java DSL フロー定義を次のように構成できます。
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlows.from("controlBus")
.controlBus()
.get();
}DirectChannel の自動作成でラムダを使用する場合は、次のように制御バスを作成できます。
@Bean
public IntegrationFlow controlBus() {
return IntegrationFlowDefinition::controlBus;
} この場合、チャネルの名前は controlBus.input です。
正常なシャットダウン
"MBean エクスポーター" に従って、MBean エクスポーターは stopActiveComponents と呼ばれる JMX 操作を提供します。これは、アプリケーションを正常に停止するために使用されます。操作には単一の Long パラメーターがあります。このパラメーターは、処理中のメッセージの完了を待機する時間(ミリ秒単位)を示します。操作は次のように機能します。
OrderlyShutdownCapableを実装するすべての Bean でbeforeShutdown()を呼び出します。そうすることで、そのようなコンポーネントはシャットダウンの準備ができます。このインターフェースを実装するコンポーネントの例と、この呼び出しで行うことには、リスナーコンテナーを停止する JMS および AMQP メッセージ駆動型アダプター、新しい接続の受け入れを停止する(既存の接続を開いたまま)TCP サーバー接続ファクトリ、ドロップする TCP 受信エンドポイントが含まれます(ログ)受信した新しいメッセージ、新しいリクエストに対して
503 - Service Unavailableを返す HTTP 受信エンドポイント。JMS または AMQP-backed チャネルなどのアクティブなチャネルを停止します。
すべての
MessageSourceインスタンスを停止します。すべての受信
MessageProducerを停止します(OrderlyShutdownCapableではありません)。操作に渡される
Longパラメーターの値で定義されているように、残り時間が残っているのを待ちます。そうすることで、飛行中のメッセージがすべての旅を完了することができます。この操作を呼び出すときに適切なタイムアウトを選択することが重要です。
すべての
OrderlyShutdownCapableコンポーネントでafterShutdown()を呼び出します。これにより、そのようなコンポーネントは最終的なシャットダウンタスクを実行できます(たとえば、開いているすべてのソケットを閉じる)。
正常なシャットダウン管理操作で説明したように、この操作は JMX を使用して呼び出すことができます。プログラムでメソッドを呼び出す場合は、IntegrationMBeanExporter への参照を挿入するか、取得する必要があります。id 属性が <int-jmx:mbean-export/> 定義で指定されていない場合、Bean には名前が生成されます。この名前には、同じ JVM(MBeanServer)に複数の Spring Integration コンテキストが存在する場合に ObjectName の衝突を回避するためのランダムなコンポーネントが含まれています。
このため、プログラムでメソッドを呼び出す場合は、アプリケーションコンテキストで簡単にアクセスできるように、エクスポーターに id 属性を提供することをお勧めします。
最後に、<control-bus> 要素を使用して操作を呼び出すことができます。詳細については、モニタリング Spring Integration サンプルアプリケーション [GitHub] (英語) を参照してください。
前述のアルゴリズムは、バージョン 4.1 で改善されました。以前は、すべてのタスクエグゼキューターとスケジューラーが停止していました。これにより、QueueChannel インスタンスの中間フローメッセージが残る可能性があります。これで、シャットダウンによりポーラーが実行されたままになり、これらのメッセージを排出して処理できるようになります。 |
統合グラフ
バージョン 4.3 から、Spring Integration はアプリケーションのランタイムオブジェクトモデルへのアクセスを提供します。これには、オプションでコンポーネントメトリクスを含めることができます。グラフとして公開され、統合アプリケーションの現在の状態を視覚化するために使用できます。o.s.i.support.management.graph パッケージには、Spring Integration コンポーネントのランタイム状態を単一のツリーのような Graph オブジェクトとして収集、構築、レンダリングするために必要なすべてのクラスが含まれています。IntegrationGraphServer は、Graph オブジェクトを作成、取得、リフレッシュするために Bean として宣言する必要があります。結果の Graph オブジェクトは任意の形式に直列化できますが、JSON はクライアント側で解析および表現するのに柔軟で便利です。デフォルトのコンポーネントのみを持つ Spring Integration アプリケーションは、次のようなグラフを公開します。
{
"contentDescriptor" : {
"providerVersion" : "5.3.0.RELEASE",
"providerFormatVersion" : 1.2,
"provider" : "spring-integration",
"name" : "myAppName:1.0"
},
"nodes" : [ {
"nodeId" : 1,
"componentType" : "null-channel",
"integrationPatternType" : "null_channel",
"integrationPatternCategory" : "messaging_channel",
"properties" : { },
"sendTimers" : {
"successes" : {
"count" : 1,
"mean" : 0.0,
"max" : 0.0
},
"failures" : {
"count" : 0,
"mean" : 0.0,
"max" : 0.0
}
},
"receiveCounters" : {
"successes" : 0,
"failures" : 0
},
"name" : "nullChannel"
}, {
"nodeId" : 2,
"componentType" : "publish-subscribe-channel",
"integrationPatternType" : "publish_subscribe_channel",
"integrationPatternCategory" : "messaging_channel",
"properties" : { },
"sendTimers" : {
"successes" : {
"count" : 1,
"mean" : 7.807002,
"max" : 7.807002
},
"failures" : {
"count" : 0,
"mean" : 0.0,
"max" : 0.0
}
},
"name" : "errorChannel"
}, {
"nodeId" : 3,
"componentType" : "logging-channel-adapter",
"integrationPatternType" : "outbound_channel_adapter",
"integrationPatternCategory" : "messaging_endpoint",
"properties" : { },
"output" : null,
"input" : "errorChannel",
"sendTimers" : {
"successes" : {
"count" : 1,
"mean" : 6.742722,
"max" : 6.742722
},
"failures" : {
"count" : 0,
"mean" : 0.0,
"max" : 0.0
}
},
"name" : "errorLogger"
} ],
"links" : [ {
"from" : 2,
"to" : 3,
"type" : "input"
} ]
} バージョン 5.2 では、メトリクス管理で説明したように、Micrometer メーターに代わってレガシーメトリクスが非推奨となりました。上には表示されていませんが、レガシーメトリクス(stats 子ノードの下)は引き続きグラフに表示されますが、追加の子ノード "deprecated" : "stats are deprecated in favor of sendTimers and receiveCounters" があります。 |
一部の JSON シリアライザーでは、いくつかの手法を使用して、レガシー統計の組み込みを抑制できます。たとえば、Jackson を使用すると、NullSerializer で構成された SimpleModule を ObjectMapper に登録できます。
objectMapper.registerModule(new SimpleModule()
.addSerializer(IntegrationNode.Stats.class, NullSerializer.instance)); 結果の json には "stats" : null が含まれます。
前の例では、グラフは 3 つの最上位要素で構成されています。
contentDescriptor グラフ要素には、データを提供するアプリケーションに関する一般情報が含まれています。name は、IntegrationGraphServer Bean または spring.application.name アプリケーションコンテキスト環境プロパティでカスタマイズできます。他のプロパティはフレームワークによって提供され、同様のモデルを他のソースと区別できます。
links グラフ要素は、nodes グラフ要素のノード間の接続を表します。ソース Spring Integration アプリケーションの統合コンポーネント間の接続を表します。例: MessageChannel から MessageHandler を含む EventDrivenConsumer へ、または AbstractReplyProducingMessageHandler から MessageChannel へ。便宜上、リンクの目的を判断できるように、モデルには type 属性が含まれています。可能な型は次のとおりです。
input:MessageChannelからエンドポイント、inputChannel、requestChannelプロパティへの方向を識別しますoutput:MessageHandler、MessageProducer、SourcePollingChannelAdapterからoutputChannelまたはreplyChannelプロパティを介したMessageChannelへの方向error:PollingConsumerまたはMessageProducerまたはSourcePollingChannelAdapter上のMessageHandlerからerrorChannelプロパティを介してMessageChannelへ。discard:errorChannelプロパティを介してDiscardingMessageHandler(MessageFilterなど)からMessageChannelへ。route:AbstractMappingMessageRouter(HeaderValueRouterなど)からMessageChannelへ。outputに似ていますが、実行時に決定されます。構成されたチャネルマッピングまたは動的に解決されたチャネルの場合があります。通常、ルーターはこの目的のために最大 100 個の動的ルートのみを保持しますが、dynamicChannelLimitプロパティを設定することでこの値を変更できます。
この要素からの情報を視覚化ツールで使用して、nodes グラフ要素のノード間の接続をレンダリングできます。from および to 番号は、リンクされたノードの nodeId プロパティの値を表します。例: link 要素を使用して、ターゲットノードで適切な port を決定できます。
次の「テキストイメージ」は、型間の関連を示しています。
+---(discard)
|
+----o----+
| |
| |
| |
(input)--o o---(output)
| |
| |
| |
+----o----+
|
+---(error)nodes グラフ要素は、おそらく最も興味深いものです。その要素には、componentType インスタンスと name 値を持つランタイムコンポーネントが含まれるだけでなく、オプションでコンポーネントによって公開されるメトリクスも含まれる可能性があるためです。ノード要素には、一般的に一目でわかるさまざまなプロパティが含まれています。例: 式ベースのコンポーネントには、コンポーネントの 1 次式文字列を含む expression プロパティが含まれます。メトリクスを有効にするには、@EnableIntegrationManagement を @Configuration クラスに追加するか、<int:management/> 要素を XML 構成に追加します。詳細については、指標と管理を参照してください。
nodeId は、あるコンポーネントと別のコンポーネントを区別できるようにする一意の増分識別子を表します。links 要素でも使用され、このコンポーネントと他のコンポーネント(ある場合)との関連(接続)を表します。input および output 属性は、AbstractEndpoint、MessageHandler、SourcePollingChannelAdapter または MessageProducerSupport の inputChannel および outputChannel プロパティ用です。詳細については、次のセクションを参照してください。
バージョン 5.1 以降、IntegrationGraphServer は、特定の NamedComponent の IntegrationNode 上の追加プロパティの作成に Function<NamedComponent, Map<String, Object>> additionalPropertiesCallback を受け入れます。たとえば、SmartLifecycle autoStartup、running プロパティをターゲットグラフに公開できます。
server.setAdditionalPropertiesCallback(namedComponent -> {
Map<String, Object> properties = null;
if (namedComponent instanceof SmartLifecycle) {
SmartLifecycle smartLifecycle = (SmartLifecycle) namedComponent;
properties = new HashMap<>();
properties.put("auto-startup", smartLifecycle.isAutoStartup());
properties.put("running", smartLifecycle.isRunning());
}
return properties;
});グラフランタイムモデル
Spring Integration コンポーネントには、さまざまなレベルの複雑さがあります。例: ポーリングされた MessageSource には、ソースデータからメッセージを定期的に送信する SourcePollingChannelAdapter と MessageChannel もあります。他のコンポーネントは、メッセージ用の requestChannel (input)にサブスクライブ(またはポーリング)するための消費 AbstractEndpoint と、ダウンストリームに送信するための応答メッセージを生成する replyChannel (output)を備えたミドルウェアのリクエスト / 応答コンポーネント(JmsOutboundGateway など)です。一方、MessageProducerSupport 実装(ApplicationEventListeningMessageProducer など)は、一部のソースプロトコルリスニングロジックをラップし、outputChannel にメッセージを送信します。
グラフ内で、Spring Integration コンポーネントは、IntegrationNode クラス階層を使用して表されます。これは、o.s.i.support.management.graph パッケージに含まれています。例: AggregatingMessageHandler には ErrorCapableDiscardingMessageHandlerNode を使用でき(discardChannel オプションがあるため)、PollingConsumer を使用して PollableChannel からコンシュームするときにエラーを生成できます。もう 1 つの例は CompositeMessageHandlerNode です。EventDrivenConsumer を使用して SubscribableChannel にサブスクライブした場合の MessageHandlerChain 用です。
@MessagingGateway (メッセージングゲートウェイを参照)は、各メソッドにノードを提供します。name 属性は、ゲートウェイの Bean 名と短いメソッドシグネチャーに基づいています。ゲートウェイの次の例を検討してください。 |
@MessagingGateway(defaultRequestChannel = "four")
public interface Gate {
void foo(String foo);
void foo(Integer foo);
void bar(String bar);
}前述のゲートウェイは、次のようなノードを生成します。
{
"nodeId" : 10,
"name" : "gate.bar(class java.lang.String)",
"stats" : null,
"componentType" : "gateway",
"integrationPatternType" : "gateway",
"integrationPatternCategory" : "messaging_endpoint",
"output" : "four",
"errors" : null
},
{
"nodeId" : 11,
"name" : "gate.foo(class java.lang.String)",
"stats" : null,
"componentType" : "gateway",
"integrationPatternType" : "gateway",
"integrationPatternCategory" : "messaging_endpoint",
"output" : "four",
"errors" : null
},
{
"nodeId" : 12,
"name" : "gate.foo(class java.lang.Integer)",
"stats" : null,
"componentType" : "gateway",
"integrationPatternType" : "gateway",
"integrationPatternCategory" : "messaging_endpoint",
"output" : "four",
"errors" : null
} この IntegrationNode 階層を使用して、クライアント側でグラフモデルを解析したり、一般的な Spring Integration ランタイムの動作を理解したりできます。詳細については、プログラミングのヒントとコツも参照してください。
バージョン 5.3 は、IntegrationPattern 抽象化と、エンタープライズ統合パターン(EIP)を表すすべての標準コンポーネントを導入し、この抽象化を実装し、IntegrationPatternType 列挙値を提供します。この情報は、ターゲットアプリケーションのいくつかの分類ロジックに役立ちます。または、グラフノードに公開されているため、UI がコンポーネントの描画方法を決定するために使用できます。
統合グラフコントローラー
アプリケーションが Web ベース(または Web コンテナーが埋め込まれた Spring Boot 上に構築されている)であり、Spring Integration HTTP または WebFlux モジュール(それぞれ HTTP サポートおよび WebFlux サポートを参照)がクラスパスに存在する場合、IntegrationGraphController を使用して IntegrationGraphServer を公開できます。REST サービスとしての機能。この目的のために、@EnableIntegrationGraphController および @Configuration クラスのアノテーションと <int-http:graph-controller/> XML 要素が HTTP モジュールで使用可能です。この構成は、@EnableWebMvc アノテーション(または XML 定義の場合は <mvc:annotation-driven/>)とともに、IntegrationGraphController @RestController を登録します。この構成では、@RequestMapping.path を @EnableIntegrationGraphController アノテーションまたは <int-http:graph-controller/> 要素で構成できます。デフォルトのパスは /integration です。
IntegrationGraphController @RestController は、次のサービスを提供します。
@GetMapping(name = "getGraph"): 最後のIntegrationGraphServerリフレッシュ以降の Spring Integration コンポーネントの状態を取得します。o.s.i.support.management.graph.Graphは、REST サービスの@ResponseBodyとして返されます。@GetMapping(path = "/refresh", name = "refreshGraph"): 実際のランタイム状態の現在のGraphをリフレッシュし、REST レスポンスとして返します。メトリクスのグラフをリフレッシュする必要はありません。グラフが取得されると、リアルタイムで提供されます。グラフが最後に取得されてからアプリケーションコンテキストが変更された場合、リフレッシュを呼び出すことができます。その場合、グラフは完全に再構築されます。
Spring Security および Spring MVC プロジェクトによって提供される標準の構成オプションとコンポーネントを使用して、IntegrationGraphController のセキュリティとクロスオリジンの制限を設定できます。次の例は、これらのゴールを達成します。
<mvc:annotation-driven />
<mvc:cors>
<mvc:mapping path="/myIntegration/**"
allowed-origins="http://localhost:9090"
allowed-methods="GET" />
</mvc:cors>
<security:http>
<security:intercept-url pattern="/myIntegration/**" access="ROLE_ADMIN" />
</security:http>
<int-http:graph-controller path="/myIntegration" />次の例は、Java 構成で同じことを行う方法を示しています。
@Configuration
@EnableWebMvc // or @EnableWebFlux
@EnableWebSecurity // or @EnableWebFluxSecurity
@EnableIntegration
@EnableIntegrationGraphController(path = "/testIntegration", allowedOrigins="http://localhost:9090")
public class IntegrationConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/testIntegration/**").hasRole("ADMIN")
// ...
.formLogin();
}
//...
} 便宜上、@EnableIntegrationGraphController アノテーションは allowedOrigins 属性を提供することに注意してください。これにより、path への GET アクセスが提供されます。より高度にするために、標準の Spring MVC メカニズムを使用して CORS マッピングを構成できます。