不惑之年的硬件牛人转到软件自学之spring cloud:(八)实现hystrix容错机制功能及整合Feign功能

前言:笔者曾经有18年的硬件研发经验,从(1)51单片机到(2)FPGA到(3)嵌入式ARM(ARM9到CORTEX A9)全都研发设计过,产品从(1)B超的整机研发到(2)智能家居系统到(3)无线电监测机到(4)平板电脑研发到(5)路灯智能控制到(5)工业电脑均有涉及,从(1)普通的电子技术工程师到(2)副总工程师到(3)副总经理到(4)事业部总经理。。。目前已经步入不惑之年的我对于物联网技术的热衷,决定从硬件开始全面转到物联技术框架之一的spring cloud技术,把我的整个学习经历和大家一起分享,也期待在之后有更多机会和大家一起合作,探讨。

         今天是:2018年4月21日(在公司加班)    研究主题:实现hystrix容错机制功能及整合Feign功能

         一、实现hystrix容错机制的目的:

         1、我们在很多系统框架设计的时候,由于不可避免的会出现部分服务或机器出问题,如下图:


     如果用户访问服务A模块,通过WEB接口或其他方式来访问基础服务模块,并访问数据库,但由于某些原因造成数据库无法访问,那么会出现用户不断地请求服务A模块,而服务A模块则继续请求基础模块并不停连接数据库,但数据库又连接不上,如此恶行循坏就会造成整个应用网络瘫痪。因为为了很好的解决这个问题,我们用Hystrix技术通过添加延迟阈值以及容错逻辑,来帮助我们控制分布式系统间组件的交付。Hystrix通过格力服务间的访问点、停止它们之间的级联故障、提供可回退操作来实现容错。

       2、就如上图所示,如果发生当前基础服务模块或数据库不可用时,服务A将对其进行“熔断”,在一定的时间内,服务A都不会再调用基础服务,以维持本身的稳定。

      

       3、我们说的以上回退逻辑方式就是断路器的开启,而断路器开启必须满足两个条件:

          第一个条件是:整个链路达到一定阈值,默认情况下,10秒内产生超过20次请求,那么这个条件实际生产过程中是可以自行设置的;比如我自己的可以服务调用者的application.yml文件中,使用如下,表示不能超过3次请求:

扫描二维码关注公众号,回复: 193869 查看本文章
circuitBreaker:
  requestVolumeThreshold: 3

         第二个条件是:  在满足第一个条件的情况下,如果请求的错误百分比大于阈值,将会打开断路器,默认为50%,而我在服务提供者的PersonController类的调用函数hello()中产生了800毫秒的延迟

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() throws Exception {
   Thread.sleep(800);
   return "Hello World";
}

同时在服务调用者的application.yml文件中有500毫秒的重启调用,但这样会一直调用不了服务提供者,因为时间比服务提供者时间更短,因此满足这个条件,肯定就会打开断路器了

hystrix:
  command:
    HelloClient#hello():
      execution:
        isolation:
          thread: 
            timeoutInMilliseconds: 500

以上理论一大堆,对于我做硬件的人来说太麻烦了,直接上项目实践。抓狂

二、还是沿用之前的三个项目:

 1、将“cjb-feign-eureka”改为“cjb-hystrix-eureka”注册中心项目,里面该改名字的地方自己去改,反正和项目名字对应就行了,并运行这个注册中心,在8888端口:

  

2、将“cjb-feign-server”服务提供者改为“cjb-hystrix-server”,并运行在8081端口(注意里面由于之前要跑两个端口,会有两个主程序,但这里只用一个就行了),里面该改名字的地方自己去改,反正和项目名字对应就行了,并注册到上面那个注册中心:


3、在服务提供者cjb-hystrix-server”我们只测试hellocjb( )函数的路径“/hello”,因此需要在这里加上上面说的延时时间800毫秒,表示这个函数是需要延时800毫秒后才能return的

@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hellocjb() throws Exception{
     Thread.sleep(800);
     return "cjb is good!";
}

其他地方就不用改了

三、改造服务调用者“cjb-hystrix-client”,将之前的“cjb-feign-client”改为:“cjb-hystrix-client”

1、为“pom.xml”中添加hystrix的依赖,又是在starter后面加这个,你懂噻偷笑

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.example.demo</groupId>
   <artifactId>cjb-hystrix-client</artifactId>
   <version>0.0.1-SNAPSHOT</version>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR1</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-config</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-eureka</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-ribbon</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-feign</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-hystrix</artifactId>
      </dependency>
   </dependencies>

</project>

2、在主程序“CjbClient”中增加“@EnableCircuitBreaker”的注解

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;


@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
@ServletComponentScan
@EnableFeignClients
public class CjbClient {

   @LoadBalanced
   @Bean
   public RestTemplate getRestTemplate(){
      return new RestTemplate();
   }

   public static void main(String[] args) {
      SpringApplication.run(CjbClient.class, args);
   }
}

3、在“application.yml”中增加打开feign的hystrix的开关,并请求时间500毫秒,不超过三次重连接的设置,并注意里面会有提到:PersonClient#hellocjb()这个函数的调用:也就是在personclient类中调用hellocjb()的方法:

;server:
  port: 8100
spring:
  application:
    name: cjb-hystrix-client
  cloud:
    loadbalancer:
      retry: false
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8888/eureka/
feign:
  hystrix:
    enabled: true
hystrix:
  command:
    PersonClient#hellocjb():
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 500
      circuitBreaker:
        requestVolumeThreshold: 3

4、关键的地方来了,在"PersonClient.class"中增加fallback=PersonClientFallback.class的一个回退类,表示一旦出现不能访问“ cjb-hystrix-server”的话,因为之前由于延时800毫秒,服务调用者用500毫秒的调用时间肯定访问不了,因此会出现不能访问的问题,因此就会回退到PersonClientFallback.class的代码里面,完整代码如下:

package com.example.demo;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;



@FeignClient(name = "cjb-hystrix-server",fallback = PersonClientFallback.class)
public interface PersonClient {

    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String hellocjb();



    @RequestMapping(value = "/person/{personId}",method = RequestMethod.GET)
    Person getPerson(@PathVariable("personId") Integer personId);
}

5、新增“PersonClientFallback”继承PersonClient这个类,并输出错误提示:“cjb:fallback error!”,完整代码如下:

package com.example.demo;

import org.springframework.stereotype.Component;

@Component
public class PersonClientFallback implements PersonClient {
    public String hellocjb() {
        return "cjb:fallback error!";
    }

    public Person getPerson(Integer personId) {
        return null;
    }
}

里面的两个方式用右键的“Genernate..”:


 

并修改hellocjb()方法里面的输出“cjb:fallback error!”即可。

OK,我们运行一下这个服务调用者程序,并在端口8100中运行,即可进入回退方法并会打开熔断器中:


四、紧接着我们马上实现一个监控器,也就是监控服务调用者会不会出现断路器打开的状态:

1、我们新建一个监控端叫“cjb-hystrix-dashboard”,在“pom.xml”中增加依赖actuator

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.example.demo</groupId>
   <artifactId>cjb-hystrix-dashboard</artifactId>
   <version>0.0.1-SNAPSHOT</version>

   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Dalston.SR1</version>
            <type>pom</type>
            <scope>import</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>

   <dependencies>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-hystrix</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
         <version>1.5.3.RELEASE</version>
      </dependency>
   </dependencies>

</project>

2、在主函数中指定端口8082

package com.example.demo;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard
public class MyApplication {

   public static void main(String[] args) {
      // 设置启动的服务器端口
      new SpringApplicationBuilder(MyApplication.class).properties(
            "server.port=8082").run(args);
   }
}

运行程序,并输入网址:http://localhost:8082/hystrix


在上图中输入服务调用者的网址:http://localhost:8100/hystrix.stream


五、如果需要完整代码的朋友,可以加入作者QQ群:智物联的spring cloud,入群说明:spring cloud代码需求


     


猜你喜欢

转载自blog.csdn.net/weixin_38638578/article/details/80029002