Vor HystrixCommand können Sie eine Anforderungsverarbeitung verwenden ( HystrixCollapser ist eine abstrakte übergeordnete Klasse), um mehrere Anforderungen in eine zu verschmelzen und dann Anrufe an das Backend -Abhängigkeitssystem zu initiieren.
Die folgende Abbildung zeigt die Anzahl der Threads und die Anzahl der Netzwerkverbindungen in zwei Fällen: Die erste besteht darin, keine Fusion zu verwenden, und die zweite ist die Verwendung einer Anforderungsverarbeitung (unter der Annahme, dass alle Links in einem kurzen Zeitfenster parallel sind, z. B. innerhalb von 10 ms).
Warum eine Anfrage verschmelzen?
Die Anforderungserfüllung wird verwendet, um die Anzahl der Threads und Netzwerkverbindungen zu reduzieren, die zur Durchführung von gleichzeitigen HystrixCommand -Ausführungen erforderlich sind. Die Anfrage -Merges werden automatisch durchgeführt und zwingen Entwickler nicht, stapelige Anfragen manuell zu koordinieren.
Globaler Kontext - Globaler Kontext (über alle Tomcat -Threads abspaltet)
Dieser Zusammenführungsart erfolgt auf globaler Anwendungsebene, sodass die Anforderung eines Benutzers auf jedem Tomcat -Thread zusammengeführt werden kann.
Wenn Sie beispielsweise einen HystrixCommand so konfigurieren, dass Benutzeranforderungsabhängigkeiten zum Abrufen von Filmbewertungen unterstützt werden, fügt Hystrix seine Anforderung zusammen mit einer anderen Anforderung an denselben zusammengebrochenen Netzwerkanforderungen hinzu.
Benutzeranforderungskontext - Anfrage Kontext (Einzel -Tomcat -Thread)
Wenn Sie ein HystrixCommand so konfigurieren, dass Batch -Anforderungen nur für einen einzelnen Benutzer bearbeitet werden, kann Hystrix Anforderungen in einem Tomcat -Thread (Anforderung) zusammenführen.
Wenn ein Benutzer beispielsweise ein Lesezeichen von 300 Videoobjekten laden möchte, anstatt 300 Netzwerkanforderungen auszuführen, kann Hytrix sie zu einem verschmelzen.
Hystrix ist standardmäßig Request-Scope. Um die Funktion mit Anforderungs-Scoped zu verwenden (Anfrage Caching, Anforderungskollaps, Anforderungsprotokoll), müssen Sie den Lebenszyklus HystrixRequestContext verwalten (oder einen alternativen HystrixConcurrencyStrategy implementieren)
Dies bedeutet, dass Sie den folgenden Code ausführen müssen, bevor Sie eine Anfrage ausführen:
Die Codekopie lautet wie folgt: hystrixRequestContext context = hystrixRequestContext.initializeContext ();
Und am Ende der Anfrage ausführen:
context.shutdown ();
In Standard -Javaweb -Anwendungen können Sie auch einen Servletfilter verwenden, um diesen Lebenszyklus zu initialisieren
öffentliche Klasse HystrixRequestContextServletFilter implementiert Filter {public void dofilter (ServletRequest Request, ServletResponse -Antwort, Filterchain -Kette) IOException, servleTexception {hystrixRequestContext context = hystrixrequestcontext.initializeContext (); try {chain.dofilter (Anfrage, Antwort); } endlich {context.shutdown (); }}}Konfigurieren Sie es dann in web.xml
<filter> <display-name>HystrixRequestContextServletFilter</display-name> <filter-name>HystrixRequestContextServletFilter</filter-name> <filter-class>com.netflix.hystrix.contrib.requestservlet.HystrixRequestContextServletFilter</filter-class> </filter> <Filter-mapping> <filter-name> hystrixRequestContextServletFilter </filter-name> <URL-Muster>/*</url-muden> </filtermapping>
Wenn Sie Springboot entwickeln, lautet der Code wie folgt:
@WebFilter(filterName = "hystrixRequestContextServletFilter",urlPatterns = "/*")public class HystrixRequestContextServletFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest ServletRequest, ServletResponse ServletResponse, Filterchain FilterChain) löscht IOException, ServletException {hystrixRequestContext context = hystrixRequestContext.initializeContext (); try {filterchain.dofilter (ServletRequest, ServletResponse); } endlich {context.shutdown (); }} @Override public void Destroy () {}}@SpringBootApplication@enablediscoveryClient@enableFeignclients@enableHyStrix // Dies ist erforderlich, da der Filter ansonsten ungültig ist. }}
Was kostet es, eine Zusammenführung zu beantragen?
Die Kosten für die Aktivierung der Anfrage sind die Verzögerung, bevor der tatsächliche Befehl ausgeführt wird. Die größten Kosten sind die Größe des Stapelfensters, das standardmäßig 10 ms beträgt.
Wenn Sie einen Befehl haben, der 5 ms ausführt und ein 10 -ms -Stapelfenster hat, beträgt der schlimmste Fall der Ausführungszeit 15 ms. Im Allgemeinen tritt die Anfrage nicht auf, wenn das Stapelfenster gerade geöffnet ist, sodass der Zwischenwert des Zeitfensters die Hälfte des Zeitfensters beträgt, in diesem Fall 5 ms.
Ob sich diese Kosten lohnen, hängt von dem Befehl ab, der ausgeführt wird und die Befehle mit hoher Latenz nicht von einer geringen Menge an zusätzlicher durchschnittlicher Verzögerung beeinflusst werden. Darüber hinaus ist auch der Betrag der Parallelität eines bestimmten Befehls der Schlüssel: Wenn weniger als 1 oder 2 Anfragen kombiniert werden, sind die Kosten nicht wert. Tatsächlich ist eine sequentielle Iterationsanforderung, die in einem einzelnen Thread zusammengeführt wird, ein wichtiger Leistungs Engpass, und jede Iteration wartet auf die Wartezeit von 10 ms.
Wenn jedoch ein bestimmtes Befehl gleichzeitig in großen Mengen verwendet wird und gleichzeitig Dutzende oder sogar Hunderte von Anrufen in Chargen tätigen kann, sind die Kosten normalerweise viel mehr als die Erhöhung des erreichten Durchsatzes, da Hytrix die Anzahl der von ihnen benötigten Threads reduziert, Abhängigkeiten. (Diese Passage ist nicht leicht zu verstehen. Wenn die Parallelität relativ hoch ist, sind die Kosten es wert, da Hytrix viele Threads und Verbindungsressourcen sparen kann).
Der Prozess der Anforderung des Zusammenführens (wie unten gezeigt)
Das theoretische Wissen wurde erklärt. Schauen wir uns die folgenden Beispiele an. Die folgenden Beispiele integrieren Eureka+Feign+hystrix. Das vollständige Beispiel finden Sie unter: https://github.com/jingangwang/micro-service
Entitätsklasse
public class User {private Integer id; privater String -Benutzername; privates Ganzzahlalter; public user () {} public user (Ganzzahl -ID, String -Benutzername, Ganzzahlalter) {this.id = id; this.username = userername; this.age = Alter; } public Integer getId () {return id; } public void setId (Integer id) {this.id = id; } public String getUnername () {return userername; } public void setUnername (String -Benutzername) {this.username = userername; } public Integer getage () {Return Age; } public void setage (Ganzzahl älter) {this.age = älter; } @Override public String toString () {Final StringBuffer sb = new StringBuffer ("Benutzer {"); sb.append ("id ="). append (id); sb.append (", userername = '"). append (userername) .Append ('/''); sb.Append (", age ="). append (älter); sb.Append ('}'); return sb.tostring (); }}Dienstleistercode
@RastController @requestMapping ("user") public class userController {@RequestMapping ("getUser") Public User GetUser (Integer ID) {neuer Benutzer zurückgeben (ID, "Test", 29); } @RequestMapping ("getAlluser") publiclist <Unter <User> getAlluser (String -IDs) {String [] split = ids.split (","); return arrays.aslist (split) .stream () .MAP (ID -> neuer Benutzer (Integer.ValueOf (ID), "Test"+id, 30)) .Collect (collectors.tolist ()); }}Verbrauchercode
UserFeignClient
@FeignClient(name = "eureka-provider",configuration = FeignConfiguration.class)public interface UserFeignClient { /** * Find user by id* @param id User id * @return User */ @RequestMapping(value = "user/getUser.json",method = RequestMethod.GET) User findUserById(@RequestParam("id") Integer id); /*** Überschreiten der Benutzerliste* @param ID -ID -ID -Liste* @return Benutzersammlung*/@RequestMapping (value = "user/getAlluser.json", method = requestMeth.get) Liste <Benetzels <Benutzer> findAlluser (@RequestParam ("IDS") String -IDs);}UserService (auf den globalen Kontext festgelegt)
@ServicePublic Class UserService {@autowired private userFeignClient userFeignClient; / ** * MaxRequestsinbatch Diese Eigenschaft legt die maximale Anzahl von Anforderungen für die Batch -Verarbeitung fest. Der Standardwert ist ganzzahlig. com.netflix.hystrix.hystrixcollapser.scope.global, batchMethod = "findAlluser", collapserProperties = {@hystrixProperty (name = "TimerDelayinMilliseconds", value = "5000"), @hystrixProperty (name = name = name = name = ")," maxrequestSinbatch "," 5 ")} (name =")}) = "name ="). Future <Bener> Find (Integer ID) {return null; } @HyStrixCommand (commandekey = "findAlluser") publiclist <Beus> findAlluser (Liste <Ganzzahl> ids) {return userFeignClient.findAllUser (stringutils.join (ids, ",")); }}FeignCollapSerController
@RequestMapping ("Benutzer") @rastControllerPublic -Klasse FeigncollaperController {@Autowired private userservice userService; @RequestMapping ("findUser") öffentlicher Benutzer GetUser (Integer ID) löscht ExecutionException, InterruptedException {return userService.find (id) .get (); } Im obigen Code befinden wir uns im globalen Kontext (alle Anfragen von Tomcat -Threads können zusammengeführt werden), das Fenster "Merge Time" 5s (jede Anfrage muss 5s warten, bevor die Anfrage eingeleitet wird), und die maximale Anzahl von Zusammenführungen beträgt 5. In Postanlagen initiieren wir zwei Anfragen innerhalb von 5S, die Benutzer -IDs sind jedoch unterschiedlich.
localhost: 8082/user/findUser.json? id = 123189891
localhost: 8082/user/findUser.json? id = 222222
Das Ergebnis ist in der folgenden Abbildung dargestellt, und die beiden Anfragen werden in eine Anforderungsstapelanforderung zusammengefasst.
Testen wir den Anforderungskontext (Request-Scope), fügen Sie HystrixRequestContextServletFilter hinzu und ändern Sie den Benutzerservice
HystrixRequestContextServletFilter
/** * @Author WJG * @date 2017/12/22 15:15 */ @webilter (filtername = "hystrixRequestContextServletfilter" ServleTexception {} @Override public void dofilter (ServletRequest ServletRequest, ServletResponse ServletResponse, Filterchain Filterchain) löst ioException, servleTexception {hystrixRequestContext context = hystrixRequestContext.initializeContext (); try {filterchain.dofilter (ServletRequest, ServletResponse); } endlich {context.shutdown (); }} @Override public void Destroy () {}}UserService (als Anforderungskontext festgelegt)
@ServicePublic Class UserService {@autowired private userFeignClient userFeignClient; / ** * MaxRequestsinbatch Diese Eigenschaft legt die maximale Anzahl von Anforderungen für die Batch -Verarbeitung fest. Der Standardwert ist ganzzahlig. com.netflix.hystrix.hystrixcollapser.scope.request, batchMethod = "findAlluser", collapserProperties = {@hystrixProperty (name = "TimerDelayinMilliseconds", value = "5000"), @hystrixtriperty (name = name = name = name ") Future <Bener> Find (Integer ID) {return null; } @HyStrixCommand (commandekey = "findAlluser") publiclist <Beus> findAlluser (Liste <Ganzzahl> ids) {return userFeignClient.findAllUser (stringutils.join (ids, ",")); }}FeignCollapser2Controller
@RequestMapping ("Benutzer") @rastControllerPublic Class FeignCollapser2Controller {@Autowired Private UserService UserService; @RequestMapping ("findUser2") publiclist <Unter> getUser () löst ExecutionException, InterruptedException {Future <Bener> user1 = userService.find (1989) aus; Future <Beus> user2 = userService.find (1990); LIST <BENE> user> user = new ArrayList <> (); user.add (user1.get ()); user.add (user2.get ()); Rückkehrbenutzer; }} Wir tippen Postman: Localhost: 8082/Benutzer/FindUser2.json
Sie können sehen, dass zwei aufeinanderfolgende Anrufe innerhalb einer Anfrage zusammengeführt werden. Beachten Sie, dass dies nicht möglich ist, um userServer.find (1989) .Get () direkt zu verwenden, andernfalls wird die Verarbeitung direkt gemäß der Synchronisation durchgeführt und nicht zusammengeführt. Wenn zwei Registerkarten -Seiten gleichzeitig die obige Adresse anrufen, wurde festgestellt, dass zwei Chargenanfragen eingeleitet wurden, was bedeutet, dass der Umfang der Anforderungsbereich ist.
Referenzen sind wie folgt:
https://github.com/netflix/hystrix/wiki/how-to-use
//www.vevb.com/article/140530.htm
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.