亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解spring cloud hystrix 請求合并collapsing

 更新時間:2018年05月21日 11:45:28   作者:乃刀的青春  
這篇文章主要介紹了詳解spring cloud hystrix 請求合并collapsing,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

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

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

為什么要使用請求合并?

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

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

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

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

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

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

例如,一個用戶想要加載300個視頻對象的書簽,不是去執(zhí)行300次網(wǎng)絡(luò)請求,Hystrix能夠?qū)⑺麄兒喜⒊蔀橐粋€。

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

復(fù)制代碼 代碼如下:
HystrixRequestContext  context=HystrixRequestContext.initializeContext();

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

context.shutdown();

在標(biāo)準(zhǔn)的JavaWeb應(yīng)用中,你也可以使用一個Servlet過濾器來初始化這個生命周期

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中

 <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ā)的話代碼如下:

@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() {

 }
}
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
//這個是必須的,否則filter無效
@ServletComponentScan
public class Application {

 public static void main(String[] args) {
  new SpringApplicationBuilder(Application.class).web(true).run(args);
 }

}

請求合并的成本是多少?

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

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

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

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

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

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

實體類

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();
 }
}

服務(wù)提供者代碼

@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 {
 /**
  * 根據(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(設(shè)置為全局上下文)

@Service
public class UserService {
 @Autowired
 private UserFeignClient userFeignClient;



 /**
  * maxRequestsInBatch        該屬性設(shè)置批量處理的最大請求數(shù)量,默認(rèn)值為Integer.MAX_VALUE
  * timerDelayInMilliseconds       該屬性設(shè)置多長時間之內(nèi)算一次批處理,默認(rèn)為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

@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之內(nèi)發(fā)起兩次請求,用戶id不一樣。

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

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

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

我們再來測試一下請求上下文(Request-Scope)的情況,加入上面所提到的HystrixRequestContextServletFilter,并修改UserService

HystrixRequestContextServletFilter

/**
 * @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(設(shè)置為請求上下文)

@Service
public class UserService {
 @Autowired
 private UserFeignClient userFeignClient;



 /**
  * maxRequestsInBatch        該屬性設(shè)置批量處理的最大請求數(shù)量,默認(rèn)值為Integer.MAX_VALUE
  * timerDelayInMilliseconds       該屬性設(shè)置多長時間之內(nèi)算一次批處理,默認(rèn)為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

@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

 

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

參考資料如下:

https://github.com/Netflix/Hystrix/wiki/How-To-Use
http://chabaoo.cn/article/140530.htm

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

您可能感興趣的文章:

相關(guān)文章

  • 詳談java命令的本質(zhì)邏輯揭秘

    詳談java命令的本質(zhì)邏輯揭秘

    一個簡單的java命令背后究竟做了些什么事情,很多朋友提出幾個問題,下面帶領(lǐng)大家一起學(xué)習(xí)Java命令的本質(zhì)邏輯問題,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • 使用@value注解取不到application.xml配置文件中的值問題

    使用@value注解取不到application.xml配置文件中的值問題

    這篇文章主要介紹了使用@value注解取不到application.xml配置文件中的值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Spring全局異常捕獲不生效問題的解決辦法

    Spring全局異常捕獲不生效問題的解決辦法

    Spring項目全局異常處理不生效,登錄接口報錯異常信息被直接返回到接口響應(yīng)中,本文給大家介紹了Spring全局異常捕獲不生效問題的解決辦法,文中有詳細(xì)的圖文介紹,需要的朋友可以參考下
    2024-04-04
  • JAVA中使用openoffice將Excel轉(zhuǎn)PDF再轉(zhuǎn)圖片功能的實現(xiàn)代碼

    JAVA中使用openoffice將Excel轉(zhuǎn)PDF再轉(zhuǎn)圖片功能的實現(xiàn)代碼

    這篇文章主要介紹了JAVA中使用openoffice將Excel轉(zhuǎn)PDF再轉(zhuǎn)圖片功能實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • 初學(xué)者易上手的SSH-struts2 01環(huán)境搭建(圖文教程)

    初學(xué)者易上手的SSH-struts2 01環(huán)境搭建(圖文教程)

    下面小編就為大家?guī)硪黄鯇W(xué)者易上手的SSH-struts2 01環(huán)境搭建(圖文教程)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Java中的switch新特性與使用詳解

    Java中的switch新特性與使用詳解

    這篇文章主要介紹了Java中的switch新特性與使用詳解,Switch語句可以實現(xiàn)根據(jù)某一變量選則執(zhí)行代碼塊,當(dāng)然直接使用If語句也可以做到,但是有時候使用Switch語句往往更加簡潔優(yōu)美,需要的朋友可以參考下
    2023-11-11
  • JAVA遍歷一個文件夾中的所有文件的小例子

    JAVA遍歷一個文件夾中的所有文件的小例子

    在實際項目中給定一文件夾,得到這個文件夾下所有的文件這樣的需求并不是很多,更多的是查找或是刪除某一具體的文件
    2013-10-10
  • 實例解析Java設(shè)計模式編程中的適配器模式使用

    實例解析Java設(shè)計模式編程中的適配器模式使用

    本篇文章主要通過實例對適配器模式進(jìn)行了詳解,需要的朋友可以參考下
    2017-04-04
  • spring依賴注入知識點分享

    spring依賴注入知識點分享

    在本篇文章里小編給大家整理的是關(guān)于spring依賴注入知識點以及相關(guān)代碼內(nèi)容,需要的朋友們學(xué)習(xí)下。
    2019-11-11
  • springboot配置請求超時時間(Http會話和接口訪問)

    springboot配置請求超時時間(Http會話和接口訪問)

    本文主要介紹了springboot配置請求超時時間,包含Http會話和接口訪問兩種,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07

最新評論