分散ロック
多くの状況では、あるコンテキスト (または単一のメッセージ) に対するアクションは排他的な方法で実行する必要があります。1 つの例は、現在のメッセージのメッセージグループの状態をチェックして、グループを解放できるか、それとも将来の検討のためにそのメッセージを追加できるかを判断する必要があるアグリゲーターコンポーネントです。この目的のために、Java は java.util.concurrent.locks.Lock
実装を備えた API を提供します。ただし、アプリケーションがクラスター内で分散および / または実行される場合、問題はさらに複雑になります。この場合のロックは困難であり、排他性要件を達成するには、何らかの共有状態とその特定のアプローチが必要です。
Spring Integration は、ReentrantLock
API に基づいたメモリ内 DefaultLockRegistry
実装を備えた LockRegistry
抽象化を提供します。LockRegistry
の obtain(Object)
メソッドには、特定のコンテキスト用の lock key
が必要です。例: アグリゲーターは correlationKey
を使用して、そのグループに関する操作をロックします。このようにして、異なるロックを同時に使用できます。この obtain(Object)
メソッドは java.util.concurrent.locks.Lock
インスタンス (LockRegistry
実装に応じて) を返すため、残りのロジックは標準の Java 同時実行アルゴリズムと同じです。
バージョン 6.2 以降、LockRegistry
は、ロック中にいくつかのタスクを実行するための executeLocked()
API (このインターフェースの default
メソッド) を提供します。この API の動作は、よく知られている JdbcTemplate
、JmsTemplate
、または RestTemplate
と似ています。次の例は、この API の使用箇所を示しています。
LockRegistry registry = new DefaultLockRegistry();
...
registry.executeLocked("someLockKey", () -> someExclusiveResourceCall());
このメソッドはタスク呼び出しから例外を再スローし、Lock
が中断された場合は InterruptedException
をスローします。さらに、Duration
を使用するバリアントは、lock.tryLock()
が false
を返すときに java.util.concurrent.TimeoutException
をスローします。
Spring Integration は、分散ロック用に次の LockRegistry
実装を提供します。
Spring Integration AWS [GitHub] (英語) 拡張機能は DynamoDbLockRegistry
も実装します。