• 架构师入门:Spring Cloud系列,Hystrix与Eureka的整合


        和Ribbon等组件一样,在项目中,Hystrix一般不会单独出现,而是会和Eureka等组件配套出现。在Hystrix和Eureka整合后的框架里,一般会用到Hystrix的断路器以及合并请求等特性,而在Web框架里,大多会有专门的缓存组件,所以不怎么会用到Hystrix的缓存特性。

    1 准备Eureka服务器项目

        HystrixEurekaServer项目承担着Eureka服务器的作用,这部分的代码关键点如下。

        第一,在pom.xml里,通过如下关键代码引入Eureka服务器组件的依赖包。    

    1    <dependency>
    2        <groupId>org.springframework.cloud</groupId>
    3        <artifactId>spring-cloud-starter-eureka-server</artifactId>
    4    </dependency>

        第二,在application.yml里,指定了本项目的主机名和端口号,并指定了对外提供eureka服务的Url路径,代码如下。    

    1    server:
    2      port: 8888
    3    eureka:
    4      instance:
    5        hostname: localhost
    6      client:
    7        register-with-eureka: false
    8        fetch-registry: false 
    9        serviceUrl:
    10          defaultZone: http://localhost:8888/eureka/

        第三,在ServerStarter.java里,编写启动Eureka服务的代码,这里请注意,在第2和第3行里,通过注解声明了本类是Eureka服务器的启动类。    

    1    //省略必要的package和import的代码
    2    @EnableEurekaServer
    3    @SpringBootApplication
    4    public class ServerStarter 
    5    {
    6          public static void main( String[] args )
    7        {      SpringApplication.run(ServerStarter.class, args);  }
       }

      

    2 服务提供者的代码结构

        HystrixEurekaserviceProvider项目承担着Eureka服务提供者的角色。在pom.xml里,我们除了指定Eureka的依赖包以外,还了指定了Hystrix的依赖包,关键代码如下。其中,前4行指定的是Eureka的依赖包,后4行指定的是Hystrix的依赖包。    

    1    <dependency>
    2            <groupId>org.springframework.cloud</groupId>
    3            <artifactId>spring-cloud-starter-eureka</artifactId>
    4    </dependency>
    5    <dependency>
    6            <groupId>org.springframework.cloud</groupId>
    7            <artifactId>spring-cloud-starter-hystrix</artifactId>
    8   </dependency>

       而在application.yml里,指定了本项目的服务端口是1111,对外提供的项目名是hystrixEureka,以及是向第一部分指定的Eureka服务器注册,代码如下。

    1    server:
    2      port: 1111
    3    spring:
    4      application:
    5        name: hystrixEureka
    6    eureka:  
    7      client:
    8        serviceUrl:
    9          defaultZone: http://localhost:8888/eureka/

    3 在服务提供者项目里引入断路器机制

         在服务提供者的启动类ServiceProviderApp.java里,我们是通过加入@EnableCircuitBreaker注解来启动断路器,代码如下。    

    1    //省略必要的package和import代码
    2    @SpringBootApplication
    3    @EnableEurekaClient
    4    @EnableCircuitBreaker
    5    @ServletComponentScan
    6    public class ServiceProviderApp 
    7    {
    8        public static void main( String[] args )
    9        {     SpringApplication.run(ServiceProviderApp.class, args);  }
    10    }

        在Controller.java这个控制器类里,我们是在第9行里,通过调用service类提供的方法来返回具体的OrderDetail信息,代码如下。    

    1    //省略必要的package和import代码
    2    @RestController
    3    public class Controller {
    4            @Autowired
    5        private OrderDetailService service;   
    6        //对外提供服务的getOrderDetailById方法 
    7            @RequestMapping(value = "/getOrderDetailById/{orderId}", method = RequestMethod.GET)
    8            public OrderDetail getOrderDetailById(@PathVariable("orderId")   String orderId) throws Exception {
    9            return service.getOrderDetailByID(orderId);
    10        }
    11    }

        在OrderDetailService.java里,我们用HashMap这个数据结构来模拟数据库,以此来模拟从数据库读OrderDetail的方式,提供了“根据ID找相应对象的服务”,代码如下。    

    1    //省略必要的package和import代码
    2    @Service
    3    public class OrderDetailService {
    4        static HashMap<String,String> orderDB = new HashMap<String,String> ();
    5        static //通过static代码,模拟数据库中存储的OrderDetail信息
    6        {
    7            orderDB.put("1","Peter");
    8            orderDB.put("2","Tom");
    9            orderDB.put("3","Mike");
    10        }
    11    //在方法之前,通过注解引入Hystrix,并指定回退方法
    12        @HystrixCommand(fallbackMethod = "getFallback")
    13        public OrderDetail getOrderDetailByID(String id) throws Exception
    14        {
    15            OrderDetail orderDetail = new OrderDetail();        
    16            if("error".equals(id) ) //如果输入是error,则故意抛出异常
    17            {throw new Exception(); }
    18            //模拟地从数据库里得到信息并返回
    19            orderDetail.setOrderId(id);
    20            orderDetail.setOrderOwner(orderDB.get(id));
    21            return orderDetail;
    22        }
    23        //定义Hystrix的回退方法
    24        public OrderDetail getFallback(String orderId) {
    25            OrderDetail orderDetail = new OrderDetail();
    26            orderDetail.setOrderId("error");
    27            orderDetail.setOrderOwner("error");        
    28            System.out.println("In fallbackForOrderDetail function");    
    29            return orderDetail;
    30        }
    31    }

        在第13行的getOrderDetailByID方法之前,我们在第12行通过fallbackMethod定义了回退方法,在这个方法的第16行里,我们定义了如果输入是error,那么则将抛出异常,以此触发回退方法getFallback。而在第24行定义的回退方法里,我们将返回一个ID和Owner都是error的OrderDetail对象。本类用到的OrderDetail模型类定义如下。    

    1    public class OrderDetail{
    2           private String orderId;//订单id
    3         private String orderOwner; //订单所有人 
    4        //省略必要的get和set方法
    5    }

        至此我们完成了开发工作,启动HystrixEurekaServer和HystrixEurekaserviceProvider后,如果在浏览器中输入http://localhost:1111/getOrderDetailById/1,能看到如下的输出,这说明走的是正常的流程。

    {"orderId":"1","orderOwner":"Peter"}

        但如果输入的是http://localhost:1111/getOrderDetailById/error,那么会在OrderDetailService类的getOrderDetailByID方法里抛出异常,从而走Hystrix的回退流程,由此会输入如下的语句。

            {"orderId":"error","orderOwner":"error"}

        在这个案例中,我们是在“提供者服务”的模块引入hytrix断路器,而不是在“服务调用”模块,这和项目中的常规做法相符,因为启动断路器的场景一般是“提供服务模块的流量超载”。

        本人之前写的和本文有关的Spring Cloud其它相关文章。

    Hystrix针对不可用服务的保护机制以及引入缓存

     通过案例了解Hystrix的各种基本使用方式 

  • 相关阅读:
    Stopping User Manager for UID 121” error
    IDEA——如何再次开启ESLint
    堆排序
    akka-typed(10)
    微慕WordPress小程序专业版v3.0发布
    微慕WordPress小程序增强版v2.0发布
    微慕WordPress小程序开源版v3.6发布
    微慕小程序开源版A标签优化说明
    微信小程序开放「分享到朋友圈」功能
    微信小程序直播安装和开发指南
  • 原文地址:https://www.cnblogs.com/JavaArchitect/p/9874631.html
Copyright © 2020-2023  润新知