大量请求会阻塞在Tomcat服务器上,影响其它整个服务.在复杂的分布式架构的应用程序有很多的依赖,都会不可避免地在某些时候失败.高并发的依赖失败时如果没有隔离措施,当前应用服务就有被拖垮的风险.
Spring Cloud Netflix Hystrix就是隔离措施的一种实现,可以设置在某种超时或者失败情形下断开依赖调用或者返回指定逻辑,从而提高分布式系统的稳定性.比如:订单系统请求库存系统,结果一个请求过去,因为各种原因,网络超时,在规定几秒内没反应,或者服务本身就挂了,这时候更多的请求来了,不断的请求库存服务,不断的创建线程,因为没有返回,也就资源没有释放,
这也导致了系统资源被耗尽,你的服务奔溃了,这订单系统好好的,你访问了一个可能有问题的库存系统,结果导致你的订单系统也奔溃了,你再继续调用更多的依赖服务,可会会导致更多的系统奔溃,这时候Hystrix可以实现快速失败,
如果它在一段时间内侦测到许多类似的错误,会强迫其以后的多个调用快速失败,不再访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作进而导致资源耗尽。这时候Hystrix进行FallBack操作来服务降级,
Fallback相当于是降级操作. 对于查询操作, 我们可以实现一个fallback方法, 当请求后端服务出现异常的时候, 可以使用fallback方法返回的值. fallback方法的返回值一般是设置的默认值或者来自缓存.通知后面的请求告知这服务暂时不可用了。
使得应用程序继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生。Hystrix熔断器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。
(和前面第6篇的ribbon的创建基本相同)
1、新建项目,选择Create New Project
2、 下一步
3、下一步
4、下一步
(1)
(2)
(3)
5、pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.chenclass</groupId>
<artifactId>ribbonhystrixtest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ribbonhystrixtest</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
6、配置applicatioin.properties,注册中心地址
spring.application.name=ribbonhystrixconsumer
server.port=7002
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
7、创建controller包
8、在controller包下创建TestController
package com.chenclass.ribbonhystrixtest.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
@RequestMapping("chen")
public class TestController {
@Bean
@LoadBalanced
RestTemplate initRestTemplate(){
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "helloFallBack")
@RequestMapping("testrbhy")
@ResponseBody
// public String testrb(String userName, String age){
public String testrb(){
System.out.println("testrbhy!!!");
// return restTemplate.getForEntity("http://PRODUCER/test",String.class,userName,age).getBody();
return restTemplate.getForEntity("http://xaeurekaserviceprovider/test",String.class).getBody();
}
public String helloFallBack(){
return "error";
}
}
9、修改RibbonhystrixtestApplication,添加@EnableEurekaClient和@EnableCircuitBreaker,启用服务注册
package com.chenclass.ribbonhystrixtest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker //允许断路器
public class RibbonhystrixtestApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonhystrixtestApplication.class, args);
}
}
10、下面开始负载均衡和熔断测试
11、启动注册服务器
12、启动服务提供者1
13、启动服务提供者2
为了达到测试效果,将服务器2的名称改成和服务器1一样
server.port=8763
spring.application.name=xaeurekaserviceprovider
eureka.client.service-url.defaultZone: http://localhost:8761/eureka/
14、启动上面编写的Ribbonhystrixtest
15、调用服务注册eureka在浏览器地址中输入
16、在服务器中输入负载均衡测试
http://127.0.0.1:7002/chen/testrbhy
会发现变换的调用了服务,一会儿服务1,一会儿服务2
17、现在如果我们突然将服务器2provider2模块断开,即停止下来,再来在浏览器上输入http://127.0.0.1:7002/chen/testrbhy,运行结果如下:
再次调用两轮,则只有下面的了 ,不会再出现error,已经熔断
我们看到了当轮询到第二个服务提供者的时候,即provider2,由于provider2被我们停止了,导致服务不可访问了,返回我们原先在代码中定义的服务降级后的结果error回来,当后面还有请求再也不会轮询到provider2了,
网页上永远出现hello1。