序文
作業中にこのようなシナリオが多数発生する可能性があります。インターフェイスの場合、他のいくつかのサービスからクエリメソッドを呼び出し、データをカプセル化して、必要な値を取得した後にデータを返す必要があります。
マイクロサービスでも同様の状況が発生する可能性があります。サービスのインターフェイスは、feignを数回使用して他のサービスのメソッドを呼び出してデータを取得し、最終的に目的の値を取得してフロントエンドにカプセル化する必要があります。
このようなシナリオでは、1つ以上のRPCによって呼び出されるメソッドに時間がかかる場合、インターフェイス全体の応答が非常に遅くなります。Java 8の後には、このシナリオの処理に非常に適したツールであるCompletableFutureがあります。
シーン
この章では、主にCompletableFutureの並列処理の使用法について説明し、この非常に一般的なシナリオの実際の作業にすばやく習得して適用できるようにします。CompletableFutureには多くの内部使用法がありますが、個人が使用するシナリオのほとんどは並行して処理されます。他のシナリオに関心のある人は、Baiduを個別に検索できます。
シナリオの説明:
インターフェイスを作成し、他の2つのHTTPインターフェイスを呼び出し、それぞれ24の二十四節気と星座を取得し、最後にそれらを一緒に返します。
利用方法
1.オンラインAPI
Jisu DataのWebサイトhttps://www.jisuapi.comにアクセスし、アカウントを登録します。オンラインAPIの一部を無料で使用でき、1日あたり平均100の無料の機会があり、私のような人々には完全に最適です。多くの場合、ローカルで十分なテストを行います。
ここでは、24個の二十四節気をクエリするためのAPIと星座をクエリするためのAPIを使用します。ケースコードは後で提供されますが、直接使用することもできます。
2.オンラインAPIクエリを作成します
ここでは、クエリを実行するときに時間のかかる状況をシミュレートします。
1)、24の太陽の用語を照会します
package com.example.async.service; import cn.hutool.http.HttpUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; / ** * <p> *24個のソーラーをクエリします用語サービス *</p> * * @author Fulongyuan、パブリックアカウント:[Java Sharing Inn] * @since 2022-04-26 15:25 * / @Service @ Slf4j public class TwentyFourService { public static final String APPKEY = "xxxxxx ";//アプリキーpublicstaticfinal String URL =" https://api.jisuapi.com/jieqi/query "; public String getResult(){ String url = URL +"?appkey = "+ APPKEY; String result = HttpUtil.get(url); //シミュレーション時間 try { TimeUnit.SECONDS.sleep(5); } catch(Exception e){ log.error("[24ソーラーターム]>> >>例外:{}"、e.getMessage()、e); } 結果を返す; } }}
2)、星座を照会します
パッケージcom.example.async.service; importcn.hutool.http.HttpUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; / ** * < p> *コンステレーションをクエリするためのサービス *</p> * * @author Fulongyuan Jushi、パブリックアカウント:[Java Sharing Inn] * @since 2022-04-26 15:25 * / @Service @ Slf4j public class ConstellationService { public static final String APPKEY ="xxxxxx";//アプリキーpublicstaticfinal String URL = "https://api.jisuapi.com/astro/all"; public String getResult(){ String url = URL + "?appkey =" +APPKEY; 文字列の結果=HttpUtil。get(url); //シミュレーションに時間がかかる try{ TimeUnit.SECONDS.sleep(5); } catch(Exception e){ log.error( "[Constellation] >> >> Exception:{}"、e.getMessage()、e) ; } 結果を返す; } }
3.クエリサービスを作成します
パッケージcom.example.async.service; lombok.extern.slf4j.Slf4jをインポートします。 import org.springframework.stereotype.Service; java.util.HashMapをインポートします。 java.util.Mapをインポートします。 / ** *<p> *查询服务 *</p> * * @author福隆苑居士、公众号:【Java分享客栈】 * @since 2022-04-26 17:38 * / @Service @ Slf4j publicクラスQueryService{ プライベートファイナルTwentyFourServicetwentyFourService; プライベートファイナルConstellationServiceconstellationService; public QueryService(TwentyFourService teenFourService、ConstellationService constellationService){ this.twentyFourService = 20FourService; this.constellationService = constellationService; } / ***結果 を同期的に返す *@returnresult * / public Map <String、Object> query(){ //1.24つの太陽項をクエリする StringtwentyFourResult= teenFourService.getResult() ; //2.クエリコンステレーションStringconstellationResult = constellationService.getResult(); // 3. Return Map <String、Object> map = new HashMap <>(); map.put( "twentyFourResult"、twentyFourResult); map.put ("constellationResult"、constellationResult); リターンマップ; } }
4.テストインターフェイスを作成します
ここでは、特に時間のかかる計算を追加します。
パッケージcom.example.async.controller; import cn.hutool.core.date.TimeInterval; インポートcom.example.async.service.QueryService; lombok.extern.slf4j.Slf4jをインポートします。 import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; java.util.Mapをインポートします。 / ** * < p > * _ _ _ / api ") @ Slf4j public class TestController { プライベートファイナルQueryServicequeryService; public TestController(QueryService queryService){ this.queryService = queryService; } / *** 同 法 查询 * @ return timer.start(); Map <String、Object> map = queryService.query(); map.put( "costTime"、timer.intervalMs()+ "ms"); ResponseEntity.ok()。body(map);を返します。 } }
5.効果
2つのインターフェースが戻るのに約10秒かかったことがわかります。
6.CompletableFuture並列クエリ
次に、CompletableFutureを使用してインターフェースを変換し、2つのHTTPインターフェースを並行して照会して戻ります。
パッケージcom.example.async.service; lombok.extern.slf4j.Slf4jをインポートします。 import org.springframework.stereotype.Service; java.util.HashMapをインポートします。 java.util.Mapをインポートします。 import java.util.concurrent.CompletableFuture; / ** *<p> *查询服务 *</p> * * @author福隆苑居士、公众号:【Java分享客栈】 * @since 2022-04-26 17:38 * / @Service @ Slf4j publicクラスQueryService{ プライベートファイナルTwentyFourServicetwentyFourService; プライベートファイナルConstellationServiceconstellationService; public QueryService(TwentyFourService teenFourService、ConstellationService constellationService){ this.twentyFourService = 20FourService; this.constellationService = constellationService; } / *** 非同期の戻り結果 *@returnの結果 */ public Map <String、Object> queryAsync(){ Map <String、Object> map = new HashMap <>( ); //1.24 個のソーラー用語をクエリします CompletableFuture<String>teenFourQuery = CompletableFuture.supplyAsync(twentyFourService :: getResult); twinFourQuery.thenAccept((result)-> { log.info("24個のソーラー用語をクエリします用語の結果:{} "、result); map.put(" twintyFourResult "、result); })。exceptionally((e)-> { log.error("クエリ24ソーラー用語の例外:{} "、e.getMessage ()、e); map.put( "twentyFourResult"、 ""); return null; }); //2.クエリコンステレーション CompletableFuture<String>constellationQuery = CompletableFuture.supplyAsync(constellationService :: getResult); constellationQuery.thenAccept((result)-> { return null; }); //3.allOf-両方のクエリを完了する必要があります CompletableFuture<Void>allQuery=CompletableFuture。allOf(twentyFourQuery、constellationQuery); マップを返す; } }
7.テストインターフェイスを作成します
パッケージcom.example.async.controller; import cn.hutool.core.date.TimeInterval; インポートcom.example.async.service.QueryService; lombok.extern.slf4j.Slf4jをインポートします。 import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; java.util.Mapをインポートします。 / ** * < p > * _ _ _ / api ") @ Slf4j public class TestController { プライベートファイナルQueryServicequeryService; public TestController(QueryService queryService){ this.queryService = queryService; } / *** 异0041查询 *@return結果 */ @GetMapping( "/ queryAsync") public ResponseEntity <Map <String、Object >> queryAsync(){ //计時 限TimeInterval timer = new TimeInterval(); timer.start(); Map <String、Object> map = queryService.queryAsync(); map.put( "costTime"、timer.intervalMs()+ "ms"); ResponseEntity.ok()。body(map);を返します。 } }
8.CompletableFutureエフェクト
ご覧のとおり、時間は2倍になります。
9.考える
マイクロサービスで、5つのサードパーティのlajiメーカーのインターフェースをリモートで呼び出す必要がある非常に複雑なビジネスがある場合、各インターフェースは5秒かかると想定されますが、CompletableFutureを使用して並列処理を実行するのにどのくらい時間がかかりますか?
答えは「はい」です。同期クエリには約25秒かかり、CompletableFutureの並列処理は約5秒です。つまり、同じインターフェイスで呼び出される時間のかかるインターフェイスが多いほど、CompletableFutureの最適化は大きくなります。