마이크로 서비스 아키텍처에서는 프로젝트를 많은 독립 모듈로 나누어 원격 통화를 통해 함께 작동합니다. 그러나 동시성이 높은 경우 통신 수가 증가하면 총 통신 시간이 증가 할 것입니다. 동시에 스레드 풀의 자원도 제한됩니다. 동시성 환경이 높으면 많은 수의 스레드가 대기 상태에있게되므로 응답 지연이 발생합니다. 이러한 문제를 해결하려면 Hystrix의 요청 병합을 이해해야합니다.
Hystrix에서 병합 요청은 병합 프로세서를 사용하여 동일한 서비스로 시작된 연속 요청을 하나의 처리 요청으로 병합하는 것입니다 (이러한 연속 요청의 시간 창은 기본적으로 10ms입니다). 이 과정과 관련된 핵심 클래스 중 하나는 HystrixCollapser입니다. 다음으로 Hystrix 요청 병합을 구현하는 방법을 살펴 보겠습니다.
서비스 제공 업체 인터페이스
서비스 제공 업체에 서비스 소비자가 전화 할 수 있도록 두 개의 인터페이스를 제공해야합니다.
@requestmapping ( "/getbook6") public list <book> book6 (String Ids) { System.out.println("ids>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 33, "hu shi", "none"); Add (새 책 ( "ids", "helloorld", "haha")@requestmapping ( "/getbook6/{id}"); 출판사 2 "); 반환 책;}첫 번째 인터페이스는 배치 인터페이스이고 두 번째 인터페이스는 단일 요청을 처리하는 인터페이스입니다. 배치 인터페이스에서 서비스 소비자가 보낸 IDS 매개 변수 형식은 1, 2, 3, 4 ...이 형식입니다. 정상적인 상황에서는 ID를 기반으로 해당 데이터를 쿼리 한 다음 반환 세트로 조립해야합니다. 쉬운 처리를 위해 어떤 종류의 요청에 관계없이 동일한 데이터 세트를 반환합니다. 단일 요청을 처리하기위한 인터페이스는 비교적 간단하므로 반복하지 않습니다.
소비자에게 서비스를 제공합니다
자, 서비스 제공 업체가 처리 한 후에는 소비자가 어떻게 처리 해야하는지 살펴 보겠습니다.
Bookservice
먼저 BookService에 두 가지 메소드를 추가하여 다음과 같이 서비스 제공 업체가 제공 한 인터페이스를 호출하십시오.
public book test8 (long id) {return resttemplate.getForObject ( "http : // hello-service/getbook6/{1}", book.class, id);} public list <book> test9 (list <long> ids) {system.out.println ( "test9 -----------------"+"getname (). thread.currentthread (). getName ()); book [] books = resttemplate.getForObject ( "http : // hello-service/getbook6? ids = {1}", book []. class, stringutils.join (ids, ","); return array.aslist (books);}Test8은 단일 ID를 제공하는 인터페이스를 호출하는 데 사용되며 Test9는 배치 처리의 인터페이스를 호출하는 데 사용됩니다. Test9에서는 Test9가 실행되는 스레드를 인쇄하여 실행 결과를 관찰 할 수 있습니다. 또한 RestTemplate에서 리턴 값이 컬렉션 인 경우 먼저 배열로 수신 한 다음 컬렉션으로 변환해야합니다 (아마도 다른 방법이있을 수 있습니다. 친구는 더 나은 제안을 할 수 있습니다).
BookBatchCommand
Ok, BookService의 메소드가 준비된 후에는 BookBatchCommand를 만들 수 있습니다.이 책은 다음과 같이 배치 명령입니다.
Public Class BookbatchCommand 확장 hystrixcommand <list <book>> {private list <long> ids; 개인 Bookservice Bookservice; Public BookBatchCommand (list <long> ids, bookservice bookservice) {super (setter.withGroupkey (hystrixcommandgroupkey.askey ( "collapsinggroup"))) this.ids = ids; this.bookservice = BookService; } @override protected list <book> run ()은 예외 {return bookservice.test9 (ids); }}이 수업은 실제로 이전 블로그에서 소개 한 수업과 유사합니다. 이들은 모두 HystrixCommand에서 상속되며 병합 된 요청을 처리하고 실행 방법의 BookService에서 Test9 메소드를 호출하는 데 사용됩니다.
BookCollapSecommand
다음으로 hystrixcollapser에서 상속 된 BookCollapSecommand를 작성하여 요청 병합을 구현해야합니다. 다음과 같이 :
공개 클래스 BookCollapSecommand 확장 hystrixcollapseer <list <book>, book, long> {private bookservice bookservice; 개인 긴 ID; public bookcollapsecommand (BookCollapSecommand (BookService Bookservice, Long Id) {Super.withCollapSerkey (hystrixcollapserkey.askey ( "BookCollapSecommand")). 및 CollapserPropertiesDefaults (hystrixCollapserProperties.set.seteconds (100)); this.bookservice = BookService; this.id = id; } @override public long getRequestargument () {return id; } @override protected hystrixcommand <list <book>> CreateCommand (collection <collapsedRequest <book, long >> collapsedRequests) {list <long> ids = new ArrayList <> (collapsEdRequests.size ()); ids.Addall (CollapsEdRequests.stream (). Map (collapsedRequest :: getArgument) .collect (collectors.tolist ()); BookBatchCommand BookBatchCommand = New BookBatchCommand (IDS, BookService); BookBatchCommand 반품; } @override protected void void mapResponsetorequests (list <book> batchResponse, collection <collapsedRequest <book, long >> collapsedRequests) {system.out.println ( "mapResponsetorequests"); int count = 0; for (collapsedRequest <book, long> collapsedRequest : collapsedRequests) {book book = batchResponse.get (count ++); CARLAPSEDREQUEST.SETRESPONSE (BOOK); }}}이 수업과 관련하여 다음과 같은 점을 말할 것입니다.
1. 우선, 시공 방법에서 요청 시간 창을 100ms로 설정합니다. 즉, 100ms 이내의 요청 시간 간격이있는 요청은 하나의 요청으로 병합됩니다.
2. CreateCommand 메소드는 주로 요청을 병합하고 여기에 각 단일 요청의 ID를 얻고이 단일 ID를 컬렉션에 넣은 다음 BookBatchCommand 객체를 작성한 다음이 객체를 사용하여 배치 요청을 시작하는 데 사용됩니다.
3. MapReponseTorequests 메소드는 주로 각 요청에 대한 요청 결과를 설정하는 데 사용됩니다. 이 메소드의 첫 번째 매개 변수는 배치 요청의 결과를 나타내고, 두 번째 매개 변수는 각 병합 요청을 나타냅니다. 그런 다음 BatchResponse를 통과하여 붕괴 요청에 대한 요청 결과를 설정했습니다.
자,이 모든 작업이 완료된 후에 와서 테스트 할 수 있습니다.
시험
서비스 소비자 측에서 액세스 인터페이스를 작성하여 병합 요청을 테스트합니다. 테스트 인터페이스는 다음과 같습니다.
@requestmapping ( "/test7")@responseBodyPublic void test7 ()는 executionException, InterruptedException {hystrixRequestContext context = hystrixrequestContext.initializeContext (); BookCollapSecommand BC1 = 새로운 BookCollapSecommand (BookService, 1L); BookCollapSecommand BC2 = 새로운 BookCollapSecommand (BookService, 2L); BookCollapSecommand BC3 = 새로운 BookCollapSecommand (BookService, 3L); BookCollapSecommand bc4 = 새로운 BookCollapSecommand (BookService, 4L); 미래 <Book> Q1 = BC1.Queue (); 미래 <Book> Q2 = BC2.Queue (); 미래 <Book> Q3 = BC3.Queue (); Book Book1 = q1.get (); Book Book2 = q2.get (); Book Book3 = q3.get (); Thread.sleep (3000); 미래의 <book> q4 = bc4.queue (); Book Book4 = q4.get (); System.out.println ( "Book1 >>>"+Book1); System.out.println ( "Book2 >>>"+Book2); System.out.println ( "Book3 >>>"+Book3); System.out.println ( "Book4 >>>"+Book4); context.close ();}이 테스트 인터페이스와 관련하여 다음 두 가지 요점을 말했습니다.
1. 첫째, hystrixRequestContext를 초기화해야합니다
2. BookCollapSecommand 클래스의 인스턴스를 작성하여 요청을 시작하고 먼저 3 개의 요청을 보내고 3 초 동안 잠을 자고 요청을 시작합니다. 이러한 방식으로 처음 3 개의 요청은 하나의 요청으로 병합됩니다. 네 번째 요청은 비교적 길고 간격이 비교적 길지만 별도로 처리 할 스레드를 생성하기 때문에 병합되지 않습니다.
자, 다음과 같이 실행 결과를 살펴 보겠습니다.
요청 병합은 주석을 통해 구현됩니다
자, 위의 요청 병합 방법은 작성하기가 조금 번거 롭습니다. 주석을 사용 하여이 기능을보다 우아하게 구현할 수 있습니다. 먼저 BookService에 다음과 같이 두 가지 방법을 추가하십시오.
@HyStrixCollApser (BatchMethod = "Test11", CollapSerProperties = {@hystrixProperty (name = "timerdelayinMilliseconds", value = "100"}) 공개 미래 <Book> test10 (long id) {return null;}@hystrixCommandPublic List <book> test11 (long> id> id) { System.out.println ( "test9 ---------"+ids+"thread.currentThread (). getName () :"+thread.currentThread (). getName ()); book [] books = resttemplate.getForObject ( "http : // hello-service/getbook6? ids = {1}", book []. class, stringutils.join (ids, ","); return array.aslist (books);}@HyStrixCollapSer 주석을 추가하여 Test10 메소드에서 요청 병합을 구현하고 BatchMethod 속성을 사용하여 요청 병합 후 처리 방법을 표시하고 ClapserProperties 속성을 사용하여 다른 속성을 지정하십시오.
좋아, BookService로 작성한 후 다음과 같이 직접 전화하십시오.
@requestmapping ( "/test8")@responseBodyPublic void test8 ()는 executionException, InterruptedException {hystrixRequestContext context = hystrixrequestContext.initializeContext (); Future <book> f1 = bookservice.test10 (1L); Future <book> f2 = BookService.test10 (2L); Future <book> f3 = bookservice.test10 (3L); Book B1 = f1.get (); book b2 = f2.get (); Book B3 = f3.get (); Thread.sleep (3000); Future <book> f4 = bookservice.test10 (4L); book b4 = f4.get (); System.out.println ( "B1 >>>"+B1); System.out.println ( "B2 >>>"+B2); System.out.println ( "B3 >>>"+B3); System.out.println ( "B4 >>>"+B4); context.close ();}이전의 요청과 마찬가지로 첫 세 개의 요청이 병합되고 네 번째 요청은 별도로 실행됩니다. 자, 실행 결과는 다음과 같습니다.
요약
요청 합병의 장점, 친구는 여러 요청이 일회성 처리 요청으로 병합되어 네트워크 대역폭 및 스레드 풀 리소스를 효과적으로 저장할 수 있음을 알았습니다. 그러나 장점과 단점이 있습니다. 요청 병합을 설정 한 후 요청이 5ms에서 완료되었을 수 있지만 이제 다른 요청이 있는지 확인하려면 다른 10ms를 기다려야합니다. 이러한 방식으로 요청의 시간 소비는 5ms에서 15ms로 증가합니다. 그러나 우리가 시작하려는 명령이 대지 명령 인 경우 현재 시간 창의 시간 소비가 중요하지 않기 때문에이 시점에서 요청 병합을 사용할 수 있습니다. 또한 높은 동시성은 요청 합병에 매우 중요한 시나리오입니다.
좋아, 그게 우리의 병합 요청을위한 것입니다. 궁금한 점이 있으면 메시지를 남겨두고 토론하십시오. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.