オリジナル住所:http://blog.jboost.cn/2019/07/22/springboot-async.html
事業開発では、時々、このようなSMSまたはマイクロメッセージ通知書のテンプレート、または比較的長い時間がかかりますが、メインプロセスは、このような画像の保存などのフィードバックの動作結果への即時アクセスを必要としない、同期の数など、いくつかの追加の非コア機能を、遭遇他のパートナーのデータが好きです。これらの操作が主流同期プロセスに配置されている場合は、必然的にコアプロセスのパフォーマンスに影響を与える、との問題が原因であっても、サードパーティのサービスはセルフサービスが利用できないにつながるだろう。今回は、これらの操作は、主要プロセスのパフォーマンスを改善するために、非同期、および主要プロセスの可用性を改善するために、第三者でデカップリングする必要があります。
春ブーツで、または春には、我々は非同期処理を実現し、一般的に次の方法があります。
@Asyc注釈で達成結合することにより、1 @EnableAsync
非同期イベントによって達成2.
メッセージキューを介して達成3.
1.注釈ベースの実現
私たちは、春に非同期サポートを提供するために使用さは、一般的に以下のapplicationContext.xmlを構成と同様の構成ファイルに追加されます
< タスク:注釈駆動型のエグゼキュータ=「エグゼ」 /> < タスク:エグゼキュータID =「エグゼ」プール・サイズ=「10-200」キュー容量=「2000」/>
スプリング@EnableAsyncアノテーション機能及び<task:annotation-driven/>
クラス@Configuration構成、開閉支持非同期メソッドSpringアプリケーションコンテキストに追加されているような、。@Asyncノートには、メソッドまたは非同期的に呼び出すために必要なすべてのメソッドのクラスを表すメソッドやクラスにマークすることができます。
私たちは、例えば、デモに特定の用途を持って、デモ住所:https://github.com/ronwxy/springboot-demos/tree/master/springboot-async
1. @EnableAsyncコメントを追加
@Configurationの設定クラスに@EnableAysncコメントを追加し、我々は一般的のような、スタートアップクラスに追加することができます
@SpringBootApplication @EnableAsync パブリック クラスアプリケーション{ 公共 静的 ボイドメイン(文字列[]引数){ SpringApplication.run(応用クラス、引数)。 } }
2. [設定関連の非同期実行スレッドプール
@Configuration パブリック クラス AsyncConfigは実装AsyncConfigurer { @value( "$ {async.corePoolSize:10}" ) プライベート int型corePoolSizeを。 @value( "$ {async.maxPoolSize:200}" ) プライベート int型maxPoolSize。 @value( "$ {async.queueCapacity:2000}" ) プライベート int型queueCapacity。 @value( "$ {async.keepAlive:5}" ) プライベート int型のキープアライブ。 公共執行getAsyncExecutor(){ ThreadPoolTaskExecutorキュータ =新しいThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize)。 executor.setMaxPoolSize(maxPoolSize)。 executor.setQueueCapacity(queueCapacity)。 executor.setKeepAliveSeconds(キープアライブ)。 executor.setThreadNamePrefix( "async-" ); executor.setRejectedExecutionHandler(新しいThreadPoolExecutor.CallerRunsPolicy()); executor.setDaemon(偽); // 以用户线程模式运行 executor.initialize(); リターンキュータ。 } 公共AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(){ 返す 新しいMyAsyncUncaughtExceptionHandlerを(); } パブリック 静的 クラス MyAsyncUncaughtExceptionHandlerは実装AsyncUncaughtExceptionHandler { 公共 ボイドhandleUncaughtException(Throwableをスロー可能オブジェクト、メソッドのメソッド、オブジェクト...オブジェクト){ するSystem.out.println( "キャッチ例外場合呼び出し" + method.getName())。 throwable.printStackTrace(); } } }
非同期的に実行されたときにクラスのような、非同期スレッドプール設定の方法、および例外の処理方法で構成することができます
ここでは、各パラメータが[を参照することができることを示す、非同期実行スレッドプールオブジェクトをAsyncConfigurer実装することによって、インターフェイスを提供読みを理解するために、スレッドプールの基本原理 ]、非常に詳細な紹介があります。そして、それはインターフェースを実装することで、非同期実装クラスキャッチされない例外AsyncUncaughtExceptionHandlerを処理する方法を提供します。
3.非同期メソッドを定義します。
クラスで定義された唯一の非同期メソッド(クラスがすべての注釈は、クラスメソッドの非同期実行され表す)注釈を追加したりする方法を@Asyncする、など
@Service パブリック クラスAsyncService { @Async 公共 ボイドasyncMethod(){ System.out.printlnは( "2.スレッドで実行されている:" + 。にThread.currentThread()のgetName())。 } @Async 公共 ボイドasyncMethodWithException(){ スロー 新規のRuntimeException(「非同期方法で例外を」)。 } }
4.テスト
我々は、次のテストクラスで非同期メソッドをテストすることができます
@RunWith(SpringRunner。クラス) @SpringBootTest パブリック クラスAnnotationBasedAsyncTest { @Autowired プライベートAsyncService asyncService。 @Test 公共 ボイド testAsync()はスローInterruptedExceptionある{ のSystem.out.printlnは( "1スレッドで実行されている:" + 。にThread.currentThread()のgetName())。 asyncService.asyncMethod(); Thread.sleep( 3 )。 } @Test 公共 ボイド testAysncWithException()はスローInterruptedExceptionある{ するSystem.out.printlnを("1.スレッドで実行されている:" + 。にThread.currentThread()のgetName())。 asyncService.asyncMethodWithException(); Thread.sleep( 3 )。 } }
非同期メソッドは新しいスレッドで実行されているので、それが実現した後、メインスレッドに対処するための十分な時間がかかるかもしれない、完了するのを待つために睡眠によって実行されます。特に、読者の結果はマップが存在しない、自分で実行しようとすることができます。
2.イベントの実現に基づいて、
実際にはまだ@EnableAsync @Asyncの助けを借りて、非同期実装する必要があるので、第二の方法は、イベントリスナー機構Springフレームワークによって達成され、春のデフォルトのイベントリスナーは、同期的に実行されます。
1. @EnableAsyncコメントを追加
そして、同じことが、起動クラスに追加することができます。
2.カスタムイベントクラス
ApplicationEventから継承することで、イベントを定義します
パブリック クラス MyEventは拡張ApplicationEvent { プライベート文字列の引数を、 公共MyEvent(オブジェクトソース、文字列の引数){ スーパー(ソース)。 この .arg = argに。 } // ゲッター/セッター }
3.イベントハンドラクラスを定義し
、以下のように、インターフェイスを実装することにより、二つの形式、1 ApplicationListenerをサポートしています
@Component @Async パブリック クラス MyEventHandlerが実装 ApplicationListener <MyEvent> { 公共 ボイドonApplicationEvent(MyEventイベント){ (System.out.printlnは "スレッド2に走行を" + 。にThread.currentThread()のgetName())。 System.out.println( "2引数の値:" + event.getArg()); } }
第二に、@EventListener注釈を通じて、など
@Component パブリック クラスMyEventHandler2 { @EventListener @Async 公共 ボイドハンドル(MyEventイベント){ するSystem.out.println( "スレッド3.ランニング:" + 。にThread.currentThread()のgetName())。 System.out.println( "3.引数値:" + event.getArg())。 } }
そうでない場合は、デフォルトの同期方法を実行することで、両者が@Asyncノートを追加する必要があることに注意してください。
4.クラスは、イベント送信を定義
publishEvent ApplicationEventPublisher ApplicationEventPublisherAwareインタフェース()メソッドを使用して達成することができるイベントを送信し、
@Component パブリック クラス MyEventPublisherが実装ApplicationEventPublisherAware { 保護; ApplicationEventPublisher applicationEventPublisherを 公共 ボイドsetApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher){ この .applicationEventPublisher = applicationEventPublisher。 } 公共 ボイドpublishEvent(ApplicationEventイベント){ この.applicationEventPublisher.publishEvent(イベント)。 } }
5.テスト
これは、テストクラスでテストすることができ、
@RunWith(SpringRunner。クラス) @SpringBootTest パブリック クラスEventBasedAsyncTest { @Autowired プライベートMyEventPublisher myEventPublisher。 @Test 公共 ボイド testAsync()はスローInterruptedExceptionある{ のSystem.out.printlnは( "1スレッドで実行されている:" + 。にThread.currentThread()のgetName())。 myEventPublisher.publishEvent(新しい MyEvent(この、 "テストイベントベースの非同期" )); Thread.sleep( 3 )。 } }
イベントハンドラを実行した後、両方が同じイベントMyEventを監視するように2つのクラスが、実装されていました。
3.メッセージ・キューに基づいて、
二つの方法は、サーバを実行しているマシンに基づいている上に、サーバプロセスの異常終了した場合、非同期実行の中断を引き起こす可能性があります。タスクの実行の信頼性を確保する必要がある場合は、持続性は、メッセージ・キューを利用する機構を再試行することができます。:アリクラウド上のメッセージキューサービスは、詳細については、を参照してください(などのメッセージ、タイマー/遅延情報、取引情報、の順とメッセージングのサポートのいくつかのタイプを、提供https://help.aliyun.com/document_detail/29532.html? = 5176.234368.1278132.btn4.6f43db25Rn8oey SPM )プロジェクトはアリクラウドの導入に基づいている場合、ビジネスニーズを達成するために、メッセージングサービスの一つのタイプを使用することを検討してください。
4.まとめ
信頼性がより少ない要求タスクの実行である場合にスプリングブーツの非同期処理のために、本明細書のいくつかの方法が導入され、より高い信頼性自己クラウド・メッセージ・キューのために推奨されている場合、最初のアプローチは、推奨されるまたは道のメッセージキューサービス。
この記事のデモソースアドレス:https://github.com/ronwxy/springboot-demos/tree/master/springboot-async/src/main/java/cn/jboost/async
私の個人的なブログのアドレス:HTTP://ブログ。 jboost.cn
jboost-ksxy(公共のドライ数字だけでなく歓迎注目されている技術、へのタイムリーなアクセス:私のマイクロチャネルパブリック数
更新)--------------------を-------------------------------------------