Simple use of hystrix

1. Highlights of this chapter:

What is Hystrix.
口 What problem does Hystrix solve.
The working principle of Hystrix.
How to use Hys ix when RestTemplate and Ribbon are service consumers.
How to use Hystrix when Feign is a service consumer.
How to use Hystrix Dashboard to monitor the condition of the fuse.
How to use Turbine to aggregate multiple Hystrix Dash boards.

2. What is Hystrix:

In a distributed system, the dependencies between services are intricate and complicated. An unavoidable situation is that some services will fail, causing other services that depend on them to block remote scheduling threads.
Hystrix is ​​an open source project of Netflix, which provides a fuse function to prevent linkage failures in distributed systems. Hystrix prevents linkage failures by isolating service access points
and provides solutions to failures, thereby improving the resilience of the entire distributed system.

3. What problem does Hystrix solve:

在复杂的分布式系统中,可能有几十个服务相互依赖,这些服务由于某些原因,例如机房的不可靠性、网络服务商的不可靠性等,导致某个服务不可用。
如果系统不隔离该不可用的服务,可能会导致整个系统不可用。

例如,对于依赖30 个服务的应用程序,每个服务的正常运行时间为99.99% ,对于单个服务来说, 99.99% 的可用是非常完美的。
有99.9930 = 99.7% 的可正常运行时间和0.3% 的不可用时间,那么10 亿次请求中有3000000次失败,实际的情况可能比这更糟糕。

如果不设计整个系统的韧性,即使所有依赖关系表现良好,单个服务只有0.01% 的不可用,由于整个系统的服务相互依赖,最终对整个系统的影响是非常大的。
在微服务系统中, 一个用户请求可能需要调用几个服务才能完成。如图8-1 所示,在所有的服务都处于可用状态时, 一个用户请求需要调用A 、H 、I 和P 服务。
当某一个服务,例如服务I,出现网络延迟或者故障时,即使服务A 、H 和P 可用,由于服务I 的不可用,整个用户请求会处于阻塞状态,并等待服务I 的响应。

在高并发的情况下,单个服务的延迟会导致整个请求都处于延迟状态,可能在几秒钟就使整个服务处于线程负载饱和的状态。
某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果就是整个服务的线程资源消耗殆尽。由于服务的依赖性,
会导致依赖于该故障服务的其他服务也处于线程阻塞状态,最终导致这些服务的线程资源消耗殆尽, 直到不可用,从而导致整个问服务系统都不
可用,即雪崩效应。 为了防止雪崩效应,因而产生了熔断器模型。Hystrix 是在业界表现非常好的一个熔断器模型实现的开源组件,它是Spring Cloud 组件不可缺少的一部分。

4. Hystrix's design principles:

总的来说, Hystrix 的设计原则如下。
口防止单个服务的故障耗尽整个服务的Servlet 容器(例如Tomcat )的线程资源。
口快速失败机制,如果某个服务出现了故障,则调用该服务的请求快速失败,而不是线程等待。
口提供回退( fallback )方案,在请求发生故障时,提供设定好的回退方案。
口使用熔断机制,防止故障扩散到其他服务。
口提供熔断器的监控组件Hystrix Dashboard,可以实时监控熔断器的状态。

5. Hystrix's working mechanism:

首先,当服务的某个API 接口的失败次数在一定时间内小于设定的阀值时,熔断器处于关闭状态,该API 接口正常提供服务。当该API 接口处理请求的失败次数大于设定的阀值时,
Hystrix 判定该API 接口出现了故障,打开熔断器,这时请求该API 接口会执行快速失败的逻辑(即fallback 回退的逻辑),不执行业务逻辑,请求的线程不会处于阻塞状态。
处于打开状态的熔断器, 一段时间后会处于半打开状态,并将一定数量的请求执行正常逻辑。剩余的请求会执行快速失败,若执行正常逻辑的请求失败了,则熔断器继续打开;
 若成功了,则将熔断器关闭。这样熔断器就具有了自我修复的能力。

Project demonstration
Use fuse on RestTemplate and Ribbon and use fuse on feign

Some codes of this project refer to the simple use of feign

  <modules>
        <module>eureka-client</module>   参考之前的项目
        <module>eureka-server</module> 参考之前的项目
        <module>eureka-ribbon-client</module> 新搭建
		<module>eureka-feign-client</module> 改动代码
    </modules>

One: Write Eureka Ribbon Client (demonstrate RestTemplate+Ribbon+Hystrix function):

1. Introduce dependencies in the POM file:

        <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
  1. Place application.yml
spring:
  application:
    name: eureka-ribbon-client
server:
  port: 8764

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  1. Add @EnableEurekaClient to the EurekaRibbonClientApplication to enable the Eureka Client function, and add the @EnableHystrix function to enable the Hystrix fuse function.
    Seen in the log: DiscoveryClient_EUREKA-CLIENT/localhost:eureka-ribbon-client:8764-registration status: 204 represents the service registration is successful.

  2. Create a new RibbonConfig with @Configuration annotation to identify this class as a configuration class.
    In this class, inject a Bean of RestTemplate into the IoC container, and add @LoadBalanced annotation to this Bean. At this time, RestTemplate combines with
    Ribbon to enable load balancing.

    @Configuration
public class RibbonConfig {

    /**
     * 在此类中为IoC 容器中注入一个RestTemplate 的Bean , 并在这个Bean 上加上@LoadBalanced 注解,此时RestTemplate 就结合了
     * Ribbon 开启了负载均衡功能。
     * @return
     */
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  1. Write a RibbonService class with @Service annotation, call the API interface of eureka-client with restTemplate in the hi() method of this class.
    Uri in restTemplate does not need to use hard coding (such as IP), just write the service name eureka-client and the program will automatically obtain IP and port information according to the service name eureka-client to the local cached registry list.

    Add @HystrixCommand annotation to hi() method. With the @HystrixCommand annotation, the hi() method enables the function of the Hystrix fuse, where fallbackMethod is a method for processing fallback logic.
    When the fuse is open, the fall back logic will be executed. The logic of fall back is best to return some static strings. There is no need to deal with complex logic, nor do you need to remotely schedule other services, so as to facilitate fast execution and release thread resources.
    If you must remotely schedule other services in the fallback logic, it is best to add fuses when scheduling other services remotely.

@Service
public class RibbonService {

    @Autowired
    RestTemplate restTemplate;

    /**
     * 在该类的hi()方法用restTemplate调用eureka-client的API接口  Uri 上不需要使用硬编码(比如IP),只需要写服务名eureka-client即可
     * 程序会根据服务名称 eureka-client到Eureka-server注册中心去自动获取IP和端口信息。
     *
     *
     * 在hi()方法上加@HystrixCommand 注解。有了@HystrixCommand注解, hi()方法就启用Hystrix 熔断器的功能,
     * 其中, fallbackMethod 为处理回退( fallback )逻辑的方法。
     * @param name
     * @return
     */
    @HystrixCommand(fallbackMethod = "hiError")
    public String hi(String name) {
        return restTemplate.getForObject("http://eureka-client/hi?name="+name,String.class);
    }

    public String hiError (String name){
        return "Hi," + name + ", sorry, error!";
    }
}
  1. Write a RibbonController class, add @RestController annotations to the class, enable the function of RestController, write an interface of the "/hi" Get method, and call the hi() method of the RibbonService class.
@RestController
public class RibbonController {

    /**
     * 写一个"/hi" Get 方法的接口,调用RibbonService 类的hi()方法
     */
    @Autowired
    RibbonService ribbonService;
    @GetMapping("/hi")
    public String hi(@RequestParam(required = false,defaultValue = "forezp") String name){
        return ribbonService.hi(name);
    }
 }
  1. Visit http://localhost:8765/hi?name=forezp on the browser, the browser will display the following information:
    hi forezp, i am from port:8762

  2. Close the eureka-client service.

  3. Visit http://localhost:8765/hi?name=forezp on the browser, the browser will display the following information:
    Hi,forezp, sorry, error!

    This shows that when eureka-client is not available, calling the "hi" interface of eureka-ribbon-client will enter the "/hi" method of the RibbonService class.
    Since eureka-client did not respond, it was determined that eureka-client was not available, the fuse was turned on, and finally the logic of fallbackMethod was entered.
    When the fuse is opened, subsequent requests will directly execute the logic of fallbackMethod. The advantage of this is that through fast failure, the request can be processed in time, and the thread is no longer blocked.

Write Eureka Feign Client (demonstrate Feign+Hystrix function):

yml join

# Feign 的起步依赖中已经包含Hystrix依赖,所以只要在配置文件中开启Hystrix的功能就可以
feign:
  hystrix:
    enabled: true

Modified feign interface, designated fallback as HiHystrix class

@FeignClient(value = "eureka-client",configuration = FeignConfig.class,fallback = HiHystrix.class)
public interface EurekaClientFeign {

    /**
     * 在EurekaClientFeign 接口内部有一个sayHiFromClientEureka()方法,该方法通过Feign 来调用eureka-client 服务的“/hi”的API 接口
     * @param name
     * @return
     */
    @GetMapping(value = "/hi")
    String sayHiFromClientEureka(@RequestParam(value = "name") String name);
}

HiHystrix needs to implement the feign interface and rewrite the method to handle the fuse logic

@Component
public class HiHystrix implements EurekaClientFeign {
    @Override
    public String sayHiFromClientEureka(String name) {
           return "hi,"+name+",sorry,error!";
    }
}

Access process
Visit http://localhost:8765/hi on the
browser, the browser will display the following content:
hi forezp, i am from port: 8762

Close the eureka-client service.

Visit http://localhost:8765/hi?name=forezp on the browser, the browser will display the following information:
Hi,forezp, sorry, error!

It can be seen that when eureka-client is unavailable, calling the "hi" interface of eureka-feign-client will enter the "/hi" method of the HiService class.
Since eureka-client did not respond, it was determined that eureka-client was unavailable, the fuse was turned on, and finally, it entered the logic processing class of fallback, namely HiHystrix.

Use Hystrix Dashboard in feign

Eureka-feign-client transforms the
pom file (the hystrix that comes with feign is not the initial dependency of hystrix)

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

<!-- feign 打开 Hystrix Dashboard 必须显示依赖下面3个引用-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

Startup transformation

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrixDashboard
@EnableHystrix
public class EurekaFeignClientApplication {

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

servlet

@Component
public class HystrixStreamServlet {

    @Bean
    public ServletRegistrationBean getServlet() {
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

Browser visit http://localhost:8765/hystrix.stream address: (Hystrix Dashboard above spring boot 2.0 needs to be injected with HystrixMetricsStreamServlet), otherwise http://localhost:8765/hystrix.stream will report a 404 error and
return ping:
ping:
or data :
ping: indicates
that the access is successful.

Browser visit http://localhost:8765/hystrix address:
enter in the Hystrix DashBoard input box: http://localhost:8765/hystrix.stream address
enter in Title: forezp
click on the Monitor Stream button

Display the Hystrix Dashboard data of eureka-ribbon-client. For details, please refer to: https://github.com/Netflix/Hystrix official documents (you need to access the interface http://localhost:8765/hi to display monitoring data)
(one circle, one line, seven colors)
Insert picture description here

Use turbine aggregate monitoring

The above hystrix dashboard transformation is also carried out on eureka-ribbon-client (code omitted)

New project eureka-monitor-client-8769
pom file

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

marl

spring:
  application.name: service-turbine
server:
  port: 8769

  # 1. cluster-name-expression指定集群名称,默认表达式appName;此时:turbine.app-config需要配置想要监控的应用名称
  # 2. 当cluster-name-expression: default时,turbine.aggregator.cluster-config可以不写,因为默认就是default
  # 3. 当cluster-name-expression: metadata['cluster']时,假设想要监控的应用配置了eureka.instance.metadata-map.cluster: ABC,则需要配置,同时turbine.aggregator.cluster-config: ABC
turbine:
  combine-host-port: true  #表示用host主机名和端口来区分不同服务
  app-config: eureka-ribbon-client,eureka-feign-client
  cluster-name-expression: new String("default")
  aggregator:
    cluster-config: default
  instanceUrlSuffix: /hystrix.stream # 这里必须设置,否则默认程序会读取/actuator/hystrix.stream


eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

Start class

@SpringBootApplication
@EnableTurbine
@EnableEurekaClient
@EnableHystrixDashboard
public class EurekaMonitorClientApplication {

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

Visit separately on the browser:
http://localhost:8764/hi?name=eureka-ribbon-client
http://localhost:8765/hi?name=eureka-feign-client

Visit http://localhost:8764/hystrix/ in the browser to enter the Hystrix Dashboard interface. Enter the Url address of the monitoring Liu on the interface:
http://localhost:8769/turbine.stream, the monitoring interval is 2000 milliseconds and the title, click monitor to view the Hystrix Dashboard of eureka-ribbon-client and eureka-feign-client.

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_44892460/article/details/108027672