JBoss EAP 7 はセッションのリクエストを並行処理しない

Solution Verified - Updated -

Environment

  • JBoss Enterprise Application Platform (EAP)
    • 7.x

Issue

  • 非同期サーブレット呼び出しがハングしている間に SOAP 呼び出しが呼び出されると、SOAP 呼び出しは HTTP セッションのロックの取得に失敗します。
  • セッションロックの待機中にリクエストがタイムアウトするとエラーが発生します。

    ERROR [org.infinispan.interceptors.InvocationContextInterceptor] (default task-79) ISPN000136: Error executing command GetKeyValueCommand, writing keys []: org.infinispan.util.concurrent.TimeoutException: ISPN000299: Unable to acquire lock after 15 seconds for key ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn and requestor GlobalTransaction::45:local. Lock is held by GlobalTransaction::43:local
    
  • JBoss EAP 7 が特定セッションのリクエストを処理するのは、一度に 1 つのみです。

スレッドダンプでは、ブロックされたスレッドが表示されます。

Thread 84833: (state = BLOCKED)
 - sun.misc.Unsafe.park(boolean, long) @bci=0 (Compiled frame; information may be imprecise)
 - java.util.concurrent.locks.LockSupport.parkNanos(java.lang.Object, long) @bci=20, line=215 (Compiled frame)
 - java.util.concurrent.CompletableFuture$Signaller.block() @bci=39, line=1695 (Compiled frame)
 - java.util.concurrent.ForkJoinPool.managedBlock(java.util.concurrent.ForkJoinPool$ManagedBlocker) @bci=119, line=3323 (Compiled frame)
 - java.util.concurrent.CompletableFuture.timedGet(long) @bci=142, line=1775 (Compiled frame)
 - java.util.concurrent.CompletableFuture.get(long, java.util.concurrent.TimeUnit) @bci=20, line=1915 (Compiled frame)
 - org.infinispan.util.concurrent.CompletableFutures.await(java.util.concurrent.CompletableFuture, long, java.util.concurrent.TimeUnit) @bci=19, line=74 (Compiled frame)
 - org.infinispan.util.concurrent.locks.impl.InfinispanLock$LockPlaceHolder.lock() @bci=74, line=319 (Compiled frame)
 - org.infinispan.util.concurrent.locks.impl.DefaultLockManager$KeyAwareExtendedLockPromise.lock() @bci=4, line=236 (Compiled frame)

Resolution

同時アクセスを可能にするには、web セッションのレプリケーションキャッシュ設定を変更して <locking> および <transaction> を完全に削除します。 また、EAP 7.1+ で SYNC のデフォルト設定を使用するには、「mode」属性を削除する必要があります。

  • ha ベースの設定 (standalone-ha.xml / standalone-full-ha.xml) の場合は、以下を変更します。

        <cache-container name="web" default-cache="dist" module="org.wildfly.clustering.web.infinispan">
            <transport lock-timeout="60000"/>
            <distributed-cache name="dist" mode="ASYNC" l1-lifespan="0" owners="2">
                <locking isolation="REPEATABLE_READ"/>
                <transaction mode="BATCH"/>
                <file-store/>
            </distributed-cache>
        </cache-container>
    

    変更後

        <cache-container name="web" default-cache="dist" module="org.wildfly.clustering.web.infinispan">
            <transport lock-timeout="60000"/>
            <distributed-cache name="dist" l1-lifespan="0" owners="2">
                <file-store/>
            </distributed-cache>
        </cache-container>
    

    以下の CLI を実行できます。

    /subsystem=infinispan/cache-container=web/distributed-cache=dist/component=locking:remove
    /subsystem=infinispan/cache-container=web/distributed-cache=dist/component=transaction:remove
    

    <distributed-cache> の代わりにキャッシュ定義 <replicated-cache> を使用している場合は、上記の設定の変更をキャッシュ設定に適用します。

  • non-ha ベースの設定のローカル (レプリケートされていない) キャッシュの場合 (standalone.xml / standalone-full.xml) は、以下を変更します。

        <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
            <local-cache name="passivation">
                <locking isolation="REPEATABLE_READ"/>
                <transaction mode="BATCH"/>
                <file-store passivation="true" purge="false"/>
            </local-cache>
            <local-cache name="persistent">
                <locking isolation="REPEATABLE_READ"/>
                <transaction mode="BATCH"/>
                <file-store passivation="false" purge="false"/>
            </local-cache>
        </cache-container>
    

    変更後

        <cache-container name="web" default-cache="passivation" module="org.wildfly.clustering.web.infinispan">
            <local-cache name="passivation">
                <file-store passivation="true" purge="false"/>
            </local-cache>
            <local-cache name="persistent">
                <file-store passivation="false" purge="false"/>
            </local-cache>
        </cache-container>
    

    以下の CLI を実行できます。

    /subsystem=infinispan/cache-container=web/local-cache=passivation/component=locking:remove
    /subsystem=infinispan/cache-container=web/local-cache=passivation/component=transaction:remove
    /subsystem=infinispan/cache-container=web/local-cache=persistent/component=locking:remove
    /subsystem=infinispan/cache-container=web/local-cache=persistent/component=transaction:remove
    

注記 : ただし、EAP 7.0.3 以前では、上記の設定の動作を妨げるバグがありました。これは、EAP 7.0.4 (JBEAP-6752) および 7.1.0 (JBEAP-4128) 以降では修正されたため、上記の設定を新しいバージョンに設定できます。

Root Cause

  • サーブレット仕様では、セッションのリクエストは一度に単一ノードでのみ処理される必要があります。
  • EAP 7.0 は、クラスター全体でセッションのリクエストを一度に 1 つのみ処理する場合にこれを実装します。

関連記事

How to configure and tune the session replication for EAP

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.