一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解spring cloud hystrix 請求合并collapsing

詳解spring cloud hystrix 請求合并collapsing

2021-05-03 11:36乃刀的青春 Java教程

這篇文章主要介紹了詳解spring cloud hystrix 請求合并collapsing,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

hystrixcommand之前可以使用請求合并器(hystrixcollapser就是一個抽象的父類)來把多個請求合并成一個然后對后端依賴系統(tǒng)發(fā)起調用。

下圖顯示了兩種情況下線程的數(shù)量和網(wǎng)絡的連接數(shù)的情況:第一種是不使用合并器,第二種是使用請求合并器(假設所有的鏈接都是在一個短的時間窗口內并行的,比如10ms內)。

詳解spring cloud hystrix 請求合并collapsing

為什么要使用請求合并?

使用請求合并來減少執(zhí)行并發(fā)hystrixcommand執(zhí)行所需的線程數(shù)和網(wǎng)絡連接數(shù),請求合并是自動執(zhí)行的,不會強制開發(fā)人員手動協(xié)調批處理請求。

全局上下文-global context(跨越所有tomcat線程)

這種合并類型是在全局應用級別上完成的,因此任何tomcat線程上的任何用戶的請求都可以一起合并。

例如,如果您配置一個hystrixcommand支持任何用戶請求依賴關系來檢索電影評級,那么當同一個jvm中的任何用戶線程發(fā)出這樣的請求時,hystrix會將其請求與任何其他請求一起添加到同一個已折疊網(wǎng)絡通話。

用戶請求上下文-request context(單個tomcat線程)

如果你配置一個hystrixcommand僅僅為一個單個用戶處理批量請求,hystrix可以在一個tomcat線程(請求)中合并請求。

例如,一個用戶想要加載300個視頻對象的書簽,不是去執(zhí)行300次網(wǎng)絡請求,hystrix能夠將他們合并成為一個。

hystrix默認是的就是request-scope,要使用request-scoped的功能(request caching,request collapsing, request log)你必須管理hystrixrequestcontext的生命周期(或者實現(xiàn)一個可替代的hystrixconcurrencystrategy
這就意味你在執(zhí)行一個請求之前需要執(zhí)行以下的代碼:

 

復制代碼 代碼如下:
hystrixrequestcontext  context=hystrixrequestcontext.initializecontext();

 

并且在請求的結束位置執(zhí)行:

?
1
context.shutdown();

在標準的javaweb應用中,你也可以使用一個servlet過濾器來初始化這個生命周期

?
1
2
3
4
5
6
7
8
9
10
11
12
public class hystrixrequestcontextservletfilter implements filter {
 
 public void dofilter(servletrequest request, servletresponse response, filterchain chain)
  throws ioexception, servletexception {
  hystrixrequestcontext context = hystrixrequestcontext.initializecontext();
  try {
   chain.dofilter(request, response);
  } finally {
   context.shutdown();
  }
 }
}

然后將它配置在web.xml中

?
1
2
3
4
5
6
7
8
9
<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-pattern>/*</url-pattern>
</filter-mapping>

如果你是springboot開發(fā)的話代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@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) throws ioexception, servletexception {
  hystrixrequestcontext context = hystrixrequestcontext.initializecontext();
  try{
   filterchain.dofilter(servletrequest,servletresponse);
  }finally {
   context.shutdown();
  }
 }
 
 @override
 public void destroy() {
 
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
@springbootapplication
@enablediscoveryclient
@enablefeignclients
@enablehystrix
//這個是必須的,否則filter無效
@servletcomponentscan
public class application {
 
 public static void main(string[] args) {
  new springapplicationbuilder(application.class).web(true).run(args);
 }
 
}

請求合并的成本是多少?

啟用請求合并的成本是在執(zhí)行實際命令之前的延遲。最大的成本是批處理窗口的大小,默認是10ms。

如果你有一個命令需要花費5ms去執(zhí)行并且有一個10ms的批處理窗口,執(zhí)行的時間最壞的情況是15ms,一般情況下,請求不會在批處理窗口剛打開的時候發(fā)生,所以時間窗口的中間值是時間窗口的一半,在這種情況下是5ms。

這個成本是否值得取決于正在執(zhí)行的命令,高延遲命令不會受到少量附加平均延遲的影響。而且,給定命令的并發(fā)量也是關鍵:如果很少有超過1個或2個請求被組合在一起,那么這個成本就是不值得的。事實上,在一個單線程的順序迭代請求合并將會是一個主要的性能瓶頸,每一次迭代都會等待10ms的窗口等待時間。

但是,如果一個特定的命令同時被大量使用,并且可以同時批量打幾十個甚至幾百個呼叫,那么成本通常遠遠超過所達到的吞吐量的增加,因為hystrix減少了它所需的線程數(shù)量,依賴。(這段話不太好理解,其實就是說如果并發(fā)比較高,這個成本是值得的,因為hystrix可以節(jié)省很多線程和連接資源)。

請求合并的流程(如下圖)

詳解spring cloud hystrix 請求合并collapsing

理論知識已經(jīng)講完了,下面來看看例子,下面的例子集成了eureka+feign+hystrix,完整的例子請查看:https://github.com/jingangwang/micro-service

實體類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class user {
 
 private integer id;
 private string username;
 private integer age;
 
 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(integer age) {
  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();
 }
}

服務提供者代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@feignclient(name = "eureka-provider",configuration = feignconfiguration.class)
public interface userfeignclient {
 /**
  * 根據(jù)id查找用戶
  * @param id 用戶id
  * @return  user
  */
 @requestmapping(value = "user/getuser.json",method = requestmethod.get)
 user finduserbyid(@requestparam("id") integer id);
 
 
 /**
  * 超找用戶列表
  * @param ids id列表
  * @return 用戶的集合
  */
 @requestmapping(value = "user/getalluser.json",method = requestmethod.get)
 list<user> findalluser(@requestparam("ids") string ids);
}

userservice(設置為全局上下文)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@service
public class userservice {
 @autowired
 private userfeignclient userfeignclient;
 
 
 
 /**
  * maxrequestsinbatch        該屬性設置批量處理的最大請求數(shù)量,默認值為integer.max_value
  * timerdelayinmilliseconds       該屬性設置多長時間之內算一次批處理,默認為10ms
  * @param id
  * @return
  */
 @hystrixcollapser(collapserkey = "findcollapserkey",scope = com.netflix.hystrix.hystrixcollapser.scope.global,batchmethod = "findalluser",collapserproperties = {
   @hystrixproperty(name = "timerdelayinmilliseconds",value = "5000" ),
   @hystrixproperty(name = "maxrequestsinbatch",value = "5" )
 })
 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

?
1
2
3
4
5
6
7
8
9
@requestmapping("user")
@restcontroller
public class feigncollapsercontroller {
 @autowired
 private userservice userservice;
 @requestmapping("finduser")
 public user getuser(integer id) throws executionexception, interruptedexception {
  return userservice.find(id).get();
 }

上面的代碼我們這是的是全局上下文(所有tomcat的線程的請求都可以合并),合并的時間窗口為5s(每一次請求都得等5s才發(fā)起請求),最大合并數(shù)為5。我們在postman中,5s之內發(fā)起兩次請求,用戶id不一樣。

localhost:8082/user/finduser.json?id=123189891

localhost:8082/user/finduser.json?id=222222

結果如下圖所示,兩次請求合并為一次請求批量請求。

詳解spring cloud hystrix 請求合并collapsing

我們再來測試一下請求上下文(request-scope)的情況,加入上面所提到的hystrixrequestcontextservletfilter,并修改userservice

hystrixrequestcontextservletfilter

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * @author wjg
 * @date 2017/12/22 15:15
 */
@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) throws ioexception, servletexception {
  hystrixrequestcontext context = hystrixrequestcontext.initializecontext();
  try{
   filterchain.dofilter(servletrequest,servletresponse);
  }finally {
   context.shutdown();
  }
 }
 
 @override
 public void destroy() {
 
 }
}

userservice(設置為請求上下文)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@service
public class userservice {
 @autowired
 private userfeignclient userfeignclient;
 
 
 
 /**
  * maxrequestsinbatch        該屬性設置批量處理的最大請求數(shù)量,默認值為integer.max_value
  * timerdelayinmilliseconds       該屬性設置多長時間之內算一次批處理,默認為10ms
  * @param id
  * @return
  */
 @hystrixcollapser(collapserkey = "findcollapserkey",scope = com.netflix.hystrix.hystrixcollapser.scope.request,batchmethod = "findalluser",collapserproperties = {
   @hystrixproperty(name = "timerdelayinmilliseconds",value = "5000" ),
   @hystrixproperty(name = "maxrequestsinbatch",value = "5" )
 })
 public future<user> find(integer id){
  return null;
 }
 
 @hystrixcommand(commandkey = "findalluser")
 public list<user> findalluser(list<integer> ids){
  return userfeignclient.findalluser(stringutils.join(ids,","));
 }
}

feigncollapser2controller

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@requestmapping("user")
@restcontroller
public class feigncollapser2controller {
 @autowired
 private userservice userservice;
 
 @requestmapping("finduser2")
 public list<user> getuser() throws executionexception, interruptedexception {
  future<user> user1 = userservice.find(1989);
  future<user> user2= userservice.find(1990);
  list<user> users = new arraylist<>();
  users.add(user1.get());
  users.add(user2.get());
  return users;
 }
}

我們在postman中輸入:localhost:8082/user/finduser2.json

詳解spring cloud hystrix 請求合并collapsing

可以看到一個請求內的兩次連續(xù)調用被合并了。這個地方要注意,不能直接使用userserver.find(1989).get(),否則直接按同步執(zhí)行處理,不會合并。如果兩個tab頁同時調用上述地址,發(fā)現(xiàn)發(fā)起了兩次批量請求,說明作用域是request范圍。

參考資料如下:

https://github.com/netflix/hystrix/wiki/how-to-use

http://m.ythuaji.com.cn/article/160601.html

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/heartroll/article/details/78872436

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 啪啪艹| 91成人爽a毛片一区二区 | 蜜色网| 天天操丝袜 | 青青青青久久国产片免费精品 | 亚洲 日本 天堂 国产 在线 | 99久久精品免费看国产一区二区 | 女海盗斯蒂内塔的复仇2免费观看 | 欧美性黑人巨大gaysex | 2020国产精品永久在线观看 | 性欧美xxxxx老太婆 | 别停好爽好深好大好舒服视频 | 午夜dj影院在线观看完整版 | 国产一区二区在线观看美女 | 乳环调教 | 好大好硬好深好爽想要之黄蓉 | 精品久久久久久综合网 | 国产精品毛片高清在线完整版 | 841995论坛网站2022年 | 免看一级a一片成人123 | 高清欧美不卡一区二区三区 | 国产一区二区三区在线 | 色综合久久丁香婷婷 | 精品一区heyzo在线播放 | 青青草精品在线观看 | 日韩一区视频在线 | 日本精品一区二区在线播放 | 羞羞视频免费观 | 国产91网站在线观看 | 成人国产在线视频在线观看 | 天使萌痴汉在线中文字幕 | 亚洲一区二区三区在线播放 | 亚洲精品第三页 | 人妖欧美一区二区三区四区 | 美女用屁股把人吞进肚子 | 亚洲 欧美 中文 日韩欧美 | 全色黄大色黄大片爽一次 | aaaa大片| naruto堂同人本子汉化gg | 日韩在线视频一区二区三区 | 3d动漫h在线观看网站蜜芽 |