HystrixCommandの前に、リクエストの合併( HystrixCollapserは抽象的な親クラス)を使用して、複数のリクエストを1つにマージし、バックエンド依存関係システムへの呼び出しを開始できます。
以下の図は、2つのケースでのスレッドの数とネットワーク接続の数を示しています。1つ目は合併を使用せず、2つ目はリクエストの合併を使用することです(すべてのリンクが10ms以内などの短い時間枠で並行していると仮定します)。
なぜリクエストマージを使用するのですか?
リクエストマージは、同時のHystrixCommand実行を実行するために必要なスレッドとネットワーク接続の数を減らすために使用されます。リクエストマージは自動的に実行され、開発者にバッチリクエストを手動で調整するように強制しません。
グローバルコンテキスト - グローバルコンテキスト(すべてのトムキャットスレッドにまたがる)
このマージタイプはグローバルアプリケーションレベルで行われるため、Tomcatスレッドでのユーザーのリクエストは統合できます。
たとえば、 HystrixCommandを構成してユーザーリクエストの依存関係をサポートして映画の評価を取得する場合、同じJVMのユーザースレッドがそのような要求を行うと、Hystrixは同じ崩壊したネットワークコールに他のリクエストとともにリクエストを追加します。
ユーザー要求コンテキスト - リクエストコンテキスト(単一のTomcatスレッド)
HystrixCommandを構成して、1人のユーザーのみのバッチリクエストを処理する場合、HystrixはTomcatスレッドでリクエストをマージできます(リクエスト)。
たとえば、ユーザーが300個のネットワークリクエストを実行する代わりに、300個のビデオオブジェクトのブックマークをロードしたい場合、Hystrixはそれらを1つにマージできます。
Hystrixはデフォルトではリクエストスコープです。リクエストスコープ機能(要求キャッシュ、リクエストの崩壊、リクエストログ)を使用するには、 HystrixRequestContextのライフサイクルを管理する必要があります(または、代替HystrixConcurrencyStrategyを実装)
これは、リクエストを実行する前に、次のコードを実行する必要があることを意味します。
コードコピーは次のとおりです。hystrixRequestContextコンテキスト= hystrixRequestContext.initializeContext();
リクエストの最後に実行します。
context.shutdown();
標準のJavawebアプリケーションでは、サーブレットフィルターを使用してこのライフサイクルを初期化することもできます
パブリッククラスのHystrixRequestContextServletFilterは、フィルター{public void dofilter(servletrequest request、servletResponse Response、filterchainチェーン)IoException、servletexception {hystrixRequestContext.initializeContext(); try {Chain.dofilter(request、response); }最後に{context.shutdown(); }}}次に、web.xmlで構成します
<フィルター> <ディスプレイ名> hystrixRequestContextServletfilter </display-name> <filter-name> hystrixRequestContextServletfilter </filter-name> <filter-class> com.netflix.hystrix.contrib.requestservlet.hystrixRequestextextextextextextextextextextexteletfiltter> </filttextextextextextextexteletfiltfilter <filter-name> hystrixRequestContextServletfilter </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
スプリングブートを開発している場合、コードは次のとおりです。
@webfilter(filtername = "hystrixrequestcontextservletfilter"、urlpatterns = "/*")public class hystrixRequestContextServletfilterはフィルター{@Override public void init(filterconfig filterconfig)servletexceptionをスローservletResponse servletResponse、filterchain filterchain)IoException、servletexception {hystrixRequestContext context = hystrixRequestContext.initializeContext(); try {filterchain.dofilter(servletRequest、servletResponse); }最後に{context.shutdown(); }} @Override public void Destroy(){}}@springbootapplication@enablediscoveryclient@enablefeignclient@enablehystrix // }}
マージをリクエストするコストはいくらですか?
リクエストマージを有効にするコストは、実際のコマンドが実行される前の遅延です。最大のコストは、バッチウィンドウのサイズで、デフォルトでは10ミリ秒です。
実行に5ミリ秒かかるコマンドがあり、10ミリ秒のバッチウィンドウがある場合、実行時間の最悪の場合は15msです。一般に、バッチウィンドウが開いたときにリクエストは発生しないため、時間ウィンドウの中間値は時間ウィンドウの半分です。この場合は5msです。
このコストが価値があるかどうかは、実行されるコマンドに依存し、高遅延コマンドは少量の追加の平均遅延の影響を受けません。さらに、特定のコマンドの並行性の量も重要です。1つまたは2つ未満のリクエストが組み合わされている場合、コストは価値がありません。実際、単一のスレッドでのシーケンシャル反復リクエストのマージは、主要なパフォーマンスボトルネックになり、各反復は10ミリ秒のウィンドウの待機時間を待ちます。
ただし、特定のコマンドが同時に大量に使用され、同時にバッチで数十または数百の呼び出しを行うことができる場合、ハイストリックスは必要なスレッドの数を減らすため、コストは通常達成されたスループットの増加を超えています。 (この文章は理解するのは容易ではありません。実際、同時性が比較的高い場合、Hystrixは多くのスレッドと接続リソースを節約できるため、コストは価値があります)。
マージを要求するプロセス(以下に示すように)
理論的知識が説明されています。以下の例を見てみましょう。以下の例は、Eureka+Feign+Hystrixを統合します。完全な例については、https://github.com/jingangwang/micro-serviceを確認してください
エンティティクラス
パブリッククラスユーザー{private integer id;プライベート文字列ユーザー名;民間整数年齢; public user(){} public user(integer id、string username、integer age){this.id = id; this.username = username; this.age = age; } public Integer getId(){return id; } public void setid(integer id){this.id = id; } public string getUsername(){return username; } public void setUsername(string username){this.username = username; } public Integer getage(){return age; } public void Setage(整数年齢){this.age = age; } @Override public String toString(){final StringBuffer sb = new StringBuffer( "user {"); sb.append( "id =")。append(id); sb.append( "、username = '")。append(username).append('/''); sb.append( "、age =")。append(age); sb.append( '}'); return sb.tostring(); }}サービスプロバイダーコード
@RestController @requestMapping( "user")public class usercontroller {@requestmapping( "getuser")public user getuser(integer id){return new user(id、 "test"、29); } @RequestMapping( "getAlluser")public list <user> getAlluser(string ids){string [] split = ids.split( "、"); return arrays.aslist(split).stream().map(id-> new user(integer.valueof(id)、 "test"+id、30)).collect(collectors.tolist()); }}消費者コード
userfeignclient
@feignclient(name = "eureka-provider"、configuration = feignconfiguration.class)public interface userfeignclient {/** * @param id user id * @return user */@requestmapping(value = "user/getuser.json"、method = method.get)user infinteurbyid( @remthed( "" "Ided(" "" "Id) /***ユーザーリストを超える* @Param IDS IDリスト* @returnユーザーコレクション*/@requestMapping(value = "user/getalluser.json"、method = requestmethod.get)list <user> findalluser(@requestparam( "ids")string ids);}userservice(グローバルコンテキストに設定)
@servicepublic class userservice {@autowired private userfeignclient userfeignclient; / ** * maxrequestsinbatchこのプロパティは、バッチ処理のリクエストの最大数を設定します。デフォルトはinteger.max_value * timerdelayinmillisecondsこのプロパティをカウントするのにかかる時間を設定します。 com.netflix.hystrix.hystrixcollapser.scope.global、batchmethod = "findalluser"、collapserproperties = {@hystrixproperty(name = "timerdelayinmilliseconds"、value = "5000") })public Future <user> find(integer id){return null; } @hystrixcommand(commandkey = "findalluser")public list <user> findalluser(list <integer> ids){return userfeignclient.findalluser(stringutils.join(ids、 "、")); }}feigncollapsercontroller
@RequestMapping( "user") @restcontrollerpublic class feigncollapsercontroller {@autowired private userservice userservice; @RequestMapping( "Finduser")パブリックユーザーgetUser(integer ID)Slows executionException、arturtedexception {return userservice.find(id).get(); }上記のコードでは、グローバルコンテキスト(Tomcatスレッドからのすべてのリクエストをマージできます)、マージタイムウィンドウは5秒(リクエストすべてが5秒待たなければなりません)、およびマージの最大数は5です。
localhost:8082/user/finduser.json?id = 123189891
localhost:8082/user/finduser.json?id = 222222
結果は下の図に示されており、2つのリクエストは1つのリクエストバッチ要求にマージされます。
リクエストコンテキスト(リクエストスコープ)をテストし、上記のHystrixRequestContextServletFilterを追加し、ユーザーサービスを変更します
HystrixRequestContextServletFilter
/** * @author wjg * @date 2017/12/22 15:15 */ @webfilter(filtername = "hystrixrequestcontextservletfilter"、urlpatterns = "/ *")public class hystrixrequestcontextservletefilter explementsフィルター{} @Override public void dofilter(servletRequest servletRequest、servletResponse servletResponse、filterchain filterchain)IoException、servletexceptext {hystrixRequestContext = hystrixRequestContext.initializeContext(); try {filterchain.dofilter(servletRequest、servletResponse); }最後に{context.shutdown(); }} @Override public void Destroy(){}}userservice(リクエストコンテキストとして設定)
@servicepublic class userservice {@autowired private userfeignclient userfeignclient; / ** * maxrequestsinbatchこのプロパティは、バッチ処理のリクエストの最大数を設定します。デフォルト値はinteger.max_value * timerdelayinmillisecondsこのプロパティをカウントするのにかかる時間を設定します。デフォルトは10msです。 com.netflix.hystrix.hystrixcollapser.scope.request、batchmethod = "findalluser"、collapserproperties = {@hystrixproperty(name = "timerdelayinmilliseconds"、value = "5000") })public Future <user> find(integer id){return null; } @hystrixcommand(commandkey = "findalluser")public list <user> findalluser(list <integer> ids){return userfeignclient.findalluser(stringutils.join(ids、 "、")); }}fiigncollapser2controller
@RequestMapping( "user") @restcontrollerpublic class feigncollapser2controller {@autowired private userservice userservice; @RequestMapping( "Finduser2")public list <user> getUser()throws executionexception、arturtedexception {future <user> user1 = userservice.find(1989); future <user> user2 = userservice.find(1990);リスト<ユーザー>ユーザー= new arrayList <>(); users.add(user1.get()); users.add(user2.get());ユーザーを返します。 }} Postman:localhost:8082/user/finduser2.jsonを入力します
リクエスト内の2つの連続した呼び出しがマージされていることがわかります。これはuserserver.find(1989).get()を直接使用することはできないことに注意してください。そうしないと、処理は同期に従って直接実行され、マージされません。 2つのタブページが上記のアドレスを同時に呼び出すと、2つのバッチリクエストが開始されていることがわかります。つまり、スコープがリクエストスコープであることがわかります。
参照は次のとおりです。
https://github.com/netflix/hystrix/wiki/how-to-use
//www.vevb.com/article/140530.htm
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。