• 第十九章 springboot + hystrix(1)


    hystrix是微服务中用于做熔断、降级的工具。

    作用:防止因为一个服务的调用失败、调用延时导致多个请求的阻塞以及多个请求的调用失败。

    1、pom.xml(引入hystrix-core包)

    1          <!-- hystrix -->   
    2         <dependency>
    3             <groupId>com.netflix.hystrix</groupId>
    4             <artifactId>hystrix-core</artifactId>
    5             <version>1.5.2</version>
    6         </dependency>
    View Code

    2、application.properties

    1 #hystrix
    2 hystrix.timeoutInMillions = 3000
    View Code

    说明:设置hystrix属性,如上是"服务调用超时时间",其他属性设置见:https://github.com/Netflix/Hystrix/wiki/Configuration

    3、HyStrixProperties

     1 package com.xxx.firstboot.hystrix;
     2 
     3 import org.springframework.boot.context.properties.ConfigurationProperties;
     4 import org.springframework.stereotype.Component;
     5 
     6 import lombok.Getter;
     7 import lombok.Setter;
     8 
     9 @Getter @Setter
    10 @Component
    11 @ConfigurationProperties(prefix = "hystrix")
    12 public class HyStrixProperties {
    13     private int timeoutInMillions;
    14 }
    View Code

    4、MyHyStrixCommand

     1 package com.xxx.firstboot.hystrix;
     2 
     3 import org.slf4j.Logger;
     4 import org.slf4j.LoggerFactory;
     5 
     6 import com.netflix.hystrix.HystrixCommand;
     7 import com.squareup.okhttp.OkHttpClient;
     8 import com.squareup.okhttp.Request;
     9 import com.squareup.okhttp.Response;
    10 
    11 public class MyHystrixCommand extends HystrixCommand<Response> {
    12     private static final Logger LOGGER = LoggerFactory.getLogger(MyHystrixCommand.class);
    13     private String url;
    14 
    15     public MyHystrixCommand(Setter setter, String url) {
    16         super(setter);
    17         this.url = url;
    18     }
    19 
    20     @Override
    21     protected Response run() throws Exception {
    22         LOGGER.info("服务正被调用,当前线程:'{}'", Thread.currentThread().getName());
    23         Request request = new Request.Builder().url(url).build();
    24         return new OkHttpClient().newCall(request).execute();
    25     }
    26 
    27     @Override
    28     public Response getFallback() {
    29         LOGGER.error("服务调用失败,service:'{}'");
    30         return null;
    31     }
    32 }
    View Code

    说明:

    • 该类是最关键的一个类。
    • 继承HystrixCommand<T>
    • 添加构造器,注意:无法添加无参构造器,因此该类无法作为spring的bean来进行管理
    • 程序开始时执行run(),当执行发生错误或超时时,执行getFallback()

    5、HyStrixUtil

     1 package com.xxx.firstboot.hystrix;
     2 
     3 import java.util.concurrent.ExecutionException;
     4 import java.util.concurrent.Future;
     5 
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.stereotype.Component;
     8 
     9 import com.netflix.hystrix.HystrixCommand.Setter;
    10 import com.netflix.hystrix.HystrixCommandGroupKey;
    11 import com.netflix.hystrix.HystrixCommandKey;
    12 import com.netflix.hystrix.HystrixCommandProperties;
    13 import com.squareup.okhttp.Response;
    14 
    15 @Component
    16 public class HystrixUtil {
    17 
    18     @Autowired
    19     private HyStrixProperties hp;
    20     
    21     public Response execute(String hotelServiceName, 
    22                             String hotelServiceMethodGetHotelInfo, 
    23                             String url) throws InterruptedException, ExecutionException {
    24         Setter setter = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(hotelServiceName));//被调用服务
    25         setter.andCommandKey(HystrixCommandKey.Factory.asKey(hotelServiceMethodGetHotelInfo));//被调用服务的一个被调用方法
    26         setter.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(hp.getTimeoutInMillions()));
    27         return new MyHystrixCommand(setter, url).execute();//同步执行
    28 //        Future<Response> future = new MyHystrixCommand(setter, url).queue();//异步执行
    29 //        return future.get();//需要时获取
    30     }
    31 
    32 }
    View Code

    说明:

    • hystrix的执行方式
      • 同步执行:超时时间起作用
      • 异步执行:超时时间不起作用(1.4.0之前的版本,在调用get()的时候开始计时起作用)
    • hystrix的隔离级别
      • HystrixCommandGroupKey:这个的名称设置为一个被调用的服务,eg.hotelService,所有这个服务下的方法都用同一个线程池(前提是没有配置ThreadPoolKey)
      • HystrixCommandKey:这个名称通常是被调用服务的一个方法的名字(实际上就是被调用服务某一个controller中的一个对外方法),eg.getHotelInfo()
      • ThreadPoolKey:这个用的很少,除非一个被调用服务中的有些被调用方法快、有的被调用方法慢,这样的话,就需要分别使用一个ThreadPoolKey,为每一个方法单独分配线程池

    6、application.properties

    1 service.hotel.name = hotelService
    2 service.hotel.method.getHotelInfo = getHotelInfo 
    View Code

    说明:定义被调用服务的服务名和被调用方法名,当然服务名也可以使用被调用服务的controller的简单类名。

    7、HystrixController

     1 package com.xxx.firstboot.web;
     2 
     3 import java.io.IOException;
     4 import java.util.concurrent.ExecutionException;
     5 
     6 import org.springframework.beans.factory.annotation.Autowired;
     7 import org.springframework.beans.factory.annotation.Value;
     8 import org.springframework.web.bind.annotation.RequestMapping;
     9 import org.springframework.web.bind.annotation.RequestMethod;
    10 import org.springframework.web.bind.annotation.RequestParam;
    11 import org.springframework.web.bind.annotation.RestController;
    12 
    13 import com.squareup.okhttp.Response;
    14 import com.xxx.firstboot.hystrix.HystrixUtil;
    15 
    16 @RestController
    17 @RequestMapping("/hystrix")
    18 public class HystrixController {
    19 
    20     @Value("${service.hotel.url}")
    21     private String HOTEL_URL;
    22 
    23     @Value("${service.hotel.name}")
    24     private String hotelServiceName;
    25     
    26     @Value("${service.hotel.method.getHotelInfo}")
    27     private String hotelServiceMethodGetHotelInfo;
    28     
    29     @Autowired
    30     private HystrixUtil hystrixUtil;
    31 
    32     @RequestMapping(value = "/firstHystrix", method = RequestMethod.GET)
    33     public String getHotelInfo(@RequestParam("id") int id, @RequestParam("name") String name) {
    34         String url = String.format(HOTEL_URL, id, name);
    35         Response response = null;
    36         try {
    37             response = hystrixUtil.execute(hotelServiceName, hotelServiceMethodGetHotelInfo, url);
    38             if (response != null) {
    39                 return response.body().string();
    40             }
    41         } catch (IOException e) {
    42             e.printStackTrace();
    43         } catch (InterruptedException e) {
    44             e.printStackTrace();
    45         } catch (ExecutionException e) {
    46             e.printStackTrace();
    47         } finally {
    48             if (response != null && response.body() != null) {
    49                 try {
    50                     response.body().close();// 资源关闭
    51                 } catch (IOException e) {
    52                     e.printStackTrace();
    53                 }
    54             }
    55         }
    56         return "获取酒店信息失败";
    57     }
    58 
    59 }
    View Code

    说明:

    • 使用@value做属性注入,假设我们是在consul上配置了application.properties内容,当修改了属性文件的内容后,该服务也必须重启,因为@value只读一次(没测过,同事说的)
    • 使用spring的Environment进行注入,当修改了属性文件的内容后,服务不需要重启,会每五分钟重新刷一次(没测过,同事说的)
    • 使用boot构建一个属性收集类,如上边的HyStrixProperties类,不知道是否需要重启(没测过)

    有测过的朋友和我讲一下,我有时间也会测一下。

    下边是被调用服务的代码:

    8、HotelController

     1 @RestController
     2 @RequestMapping("/hotel")
     3 @Api("HotelController相关api")
     4 public class HotelController {
     5     @ApiOperation("获取酒店Hotel信息:getHotelInfo")
     6     @RequestMapping(value="/getHotelInfo",method=RequestMethod.GET)
     7     public Hotel getHotelInfo(@RequestParam("id") int id, @RequestParam("name") String name) {
     8 //        try {
     9 //            TimeUnit.MILLISECONDS.sleep(2000);//用于测试超时
    10 //        } catch (InterruptedException e) {
    11 //            e.printStackTrace();
    12 //        }
    13         return new Hotel(id, name);
    14     }
    15 }
    View Code

    测试:启动被调用服务-->启动调用服务

    参考:

    http://blog.csdn.net/xiaoyu411502/article/details/50601687 官方的中文总结

    https://stonetingxin.gitbooks.io/hystrix/content/ 基本上是官方的中文翻译

    https://github.com/Netflix/Hystrix/wiki/Configuration hystrix配置介绍

    http://blog.vicoder.com/hystrix-configuration/ 配置介绍

    http://www.insaneprogramming.be/blog/2014/08/19/hystrix-spring-boot/ boot集成hystrix

  • 相关阅读:
    Jquery-EasyUI学习2~
    IIS——发布网站
    一致性哈希算法
    利用ZTree链接数据库实现 [权限管理]
    Form表单提交的简要方式
    Redis学习之5种数据类型操作、实现原理及应用场景
    redis对比其余数据库
    ZooKeeper概述(转)
    Zookeeper-Zookeeper可以干什么
    Java内存分配及变量存储位置实例讲解
  • 原文地址:https://www.cnblogs.com/java-zhao/p/5509593.html
Copyright © 2020-2023  润新知