2

私はサービスからメソッドを呼び出すRestControllerを持っています。メソッドは、最大20の接続を持つPostresSQLデータベースにユーザーを追加します。Spring CompletableFutureを返すトランザクションメソッド

@RestController 
public class Controller { 
    @RequestMapping(value = "/user", method = RequestMethod.POST) 
    public String addUser(@RequestBody UserInfo userInfo) { 
     Future<String> completableFuture = userService.addUser(userInfo); 
     String answer = voidCompletableFuture.get(); 
     return answer; 
    } 
} 

メソッドは、永続化データメソッドがCompletableFutureを返した後、Spring Transactionalによって注釈付けされます。複数のスレッドからメソッド "/ user"を同時に呼び出します(約100)。現在のスレッドをブロックコードの行「voidCompletableFuture.getは()」は、わずか20の同時要求が作動し、最大接続数によって、データベースにデータを追加して呼び出された場合

@Transactional 
public Future<String> addUser(UserInfo userInfo) { 
    userDao.persist(userInfo); 
    return CompletableFuture.supplyAsync(() -> { 
     try { 
      Thread.sleep(10000); 
      return "Result"; 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     return "Error"; 
    }); 
} 

。例外は、別のスレッドである:

Caused by: java.sql.SQLTransientConnectionException: Connection is not available, request timed out after 30000ms. 

私はこのコード行を削除し、その後、すべての要求が働いていると予想されるとして、データベースにデータを追加した場合。後でfuture.get()を呼び出すと、メソッド "public Future addUser(UserInfo userInfo)"の終了後にトランザクションが完了しなかったと思います。 誰かがSpringとCompletableFutureがこのように動作する理由を知っているのでしょうか、それとも別の答えがあるのでしょうか?なぜCompletableFutureのブロックが別のメソッドでトランザクションの終了に影響するのですか?なぜメソッドが現在のトランザクションを完了しておらず、ブロック内にリクエストメソッドがある場合は接続を解放しないのか?

+0

、あなたのトランザクションがすでに 'アドユーザー()'を呼び出すところに開始され、 '取得()'メソッドを呼び出す前にコミットされていない可能性があることでしょうか? –

+0

@DidierLトランザクションのログを調べました。トランザクションは 'addUser()'で始まり、 'get()'メソッドを呼び出す前に完了したトランザクションがいくつかあります。そして、 'get()'が要求をブロックしている間、トランザクションは完了するのを止めます( 'TransactionInterceptor:485:トランザクションの完了 'をログします)。そして、接続数はdataSourceの接続プールで最大になり、この例外が発生します。原因:java.sql.SQLTransientConnectionException:Connection is not available。接続が完了するのを止める理由を知らない。 –

答えて

1

spring.jpa.open-in-view=falseを追加した後、トランザクションsetUser()の後にトランザクションが停止し、要求の全プロセスで停止しません。ドキュメントから

:万が一 spring.jpa.open-in-view=true - Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.

+1

私のコメントのように見えます;-) TBH、これは(他のパフォーマンスの問題も含めて)このようないくつかの問題を引き起こす可能性があるため、オープン・イン・ビューは現在は推奨されていませんでした。しかし、既存のアプリでそれを変更すると、おそらく副作用があります。 –

+0

@DidierLコメントありがとうございます) –

関連する問題