熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点从而对延迟和故障提供更强大的容错能力。
什么是Hystrix?
在一个分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。
7.1 使用Hystrix保护应用
7.1.1 目前存在的问题
现在我们假设一下,服务提供者响应非常缓慢,那么消费者对提供者的请求就会被强制等待,直到服务返回。在高负载均衡场景下,如果不做任何处理,这种问题很可能造成所有处理用户请求的线程都被耗竭,而不能响应用户的进一步请求。
7.1.2 雪崩效应
在微服务架构中通常会有很多服务层调用,大量的微服务通过网络进行通信,从而支撑起整个系统。各个微服务之间也难免存在大量的依赖关系。然而任何服务都不是100%可用的,网络往往也是脆弱的,所以难免有些请求会失败。基础服务的故障导致级联故障,进而造成了整个系统的不可用,这种现象被称为服务雪崩效应。服务雪崩效应描述的是一种因服务提供者的不可用导致服务消费者的不可用,并将不可用逐渐放大的过程。
A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
7.1.3 解决方案:超时机制,断路器模式。
超时机制:
通过网络请求其他服务时,都必须设置超时,正常情况下,一个远程调用一般在几十毫秒内就返回了。当依赖的服务不可用,或者因为网络问题,响应时间将会变得很长(几十秒)。而通常情况下,一次远程调用对应了一个线程/进程,如果响应时间太慢,那么这个线程/进程就会得不到释放。而线程/进程都对应了系统资源,如果大量的线程/进程得不到释放,并且越积越多,服务资源就会耗尽,从而导致资深服务不可用。所以必须为每个请求设置超时。因此,必须为每个请求设置超时,让资源尽快地得到释放。
断路器模式:
当依赖的服务有大量超时的时候,再让新的请求去访问已经没有太大的意义,只会无谓的消耗现有资源。譬如我们设置了超时时间为1秒,如果短时间内有大量的请求(譬如50个)在1秒内都得不到响应,就往往意味着异常。此时就没有必要让更多的请求去访问这个依赖了,我们应该使用断路器避免资源浪费。
断路器可以实现快速失败,如果它在一段时间内侦测到许多类似的错误(譬如超时),就会强迫其以后的多个调用快速失败,不再请求所依赖的服务,从而防止应用程序不断地尝试执行可能会失败的操作,这样应用程序可以继续执行而不用等待修正错误,或者浪费CPU时间去等待长时间的超时。断路器也可以使应用程序能够诊断错误是否已经修正,如果已经修正,应用程序会再次尝试调用操作。
7.2 断路器:Hystrix客户端
较低级别的服务中的服务故障可能导致用户级联故障。当对特定服务的呼叫达到一定阈值时(Hystrix中的默认值为5秒,20次故障)电路打开,不进行通话。在错误和开路的情况下,开发人员可以提供后备。
开放式电路会停止级联故障,并允许不必要的或失败的服务时间来愈合。回退可以是另一个Hystrix受保护的调用,静态数据或一个正常的空值。回退可能被链接,所以第一个回退使得一些其他业务电话又回到静态数据。
7.3 Hystrix在Ribbon基础应用(配置到方法中)
7.3.1 pom.xml
//pom主要添加spring-cloud-starter-hystrix依赖
<?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>
<artifactId>microservice-consumer-movie-ribbon-with-hystrix</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.kevin.cloud</groupId>
<artifactId>microservice-spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 加入熔断器Hystrix的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
</dependencies>
</project>
7.3.2 application.yml
// 配置hystrix的超时机制
server:
port: 8010
context-path: /ribbon
spring:
application:
name: microservice-consumer-movie-ribbon-with-hystrix
eureka:
client:
healthcheck:
enabled: true
service-url:
defaultZone: http://kevin:123456@localhost:8761/eureka
instance:
prefer-ip-address: true
#home-page-url-path: /ribbon
#配置超时时间(默认1000ms,单位:ms),使用default,在调用方配置,被调用方的所有方法的超时时间都是该值
#优先级低于指定配置,hystrix.command.findById.execution.isolation.thread.timeoutInMilliseconds: 5000 指定findById的超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
7.3.3 ConsumerMovieRibbonWithHystrixApplication.java
// 在启动类加入@EnableCircuitBreaker //开启Hystrix断路器
package com.keivn.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
*
* @title 服务消费者
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@SpringBootApplication
@EnableEurekaClient //注册到Eureka
@EnableCircuitBreaker //开启断路器
public class ConsumerMovieRibbonWithHystrixApplication {
@Bean
@LoadBalanced //该注解让Restful拥有负载均衡的能力
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieRibbonWithHystrixApplication.class, args);
System.out.println("服务消费者启动...");
}
}
7.3.4 MovieController.java
// @HystrixCommand(fallbackMethod = "findByIdFallback")该注解是Hystrix的请求失败回退机制,创建一个与请求方法类型,参数,返回值一样的方法作为回退
package com.keivn.cloud.controller;
import com.keivn.cloud.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
//@HystrixCommand注解为方法创建调用失败的保险,fallbackMethod指定失败时需要调用的方法,
// @HystrixCommand(fallbackMethod = "findByIdFallback", commandProperties = @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"))
// 增加commandProperties属性,则是同一个线程,不然都是单独的一个线程
@GetMapping("/movie/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallback")
public User findById(@PathVariable Long id ){
return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
}
// 该方法是调用失败时方法的方法,类型和返回值都需要与请求的方法一致。
public User findByIdFallback(Long id){
User user = new User();
user.setId(0L);
return user;
}
}
7.3.5 User.java
package com.keivn.cloud.entity;
import java.io.Serializable;
import java.math.BigDecimal;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
public class User implements Serializable {
private Long id;
private String username;
private String name;
private Short age;
private BigDecimal balance;
public User() {
}
public User(Long id, String username, String name, Short age, BigDecimal balance) {
this.id = id;
this.username = username;
this.name = name;
this.balance = balance;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
7.3.6 说明
ribbon是客户端负载均衡组件。 可以使用轮询和随机方式调用服务。 当前项目是:ribbon与eureka一起使用,通过代码自定义配置Ribbon, 但是在其加入hystrix短路器,在请求方法失败时调用别的方法。
7.4 Hystrix的基础应用(Feign Hystrix回退)
Hystrix支持回退的概念,当电路断开或出现错误时执行的默认代码路径,要为给定的@FeignClient启用回退,将fallback属性设置为实现回退的类名。
7.4.1 pom.xml
//加入Hystrix的依赖spring-cloud-starter-hystrix
<?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>
<artifactId>microservice-consumer-movie-feign-with-hystrix</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.kevin.cloud</groupId>
<artifactId>microservice-spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</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-feign</artifactId>
</dependency>
<!-- 加入熔断器Hystrix的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
</dependencies>
</project>
7.4.2 application.yml
#配置文件跟之前的Feign没有什么差别
server:
port: 7901
spring:
application:
name: microservice-consumer-movie-feign-with-hystrix
eureka:
client:
healthcheck:
enabled: true
service-url:
defaultZone: http://kevin:123456@localhost:8761/eureka
instance:
prefer-ip-address: true
7.4.3 ConsumerMovieFeignWithHystrixApplication.java
//开启@EnableCircuitBreaker的功能
package com.keivn.cloud;
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;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
/**
*
* @title 服务消费者
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@SpringBootApplication
@EnableEurekaClient //注册到Eureka
@EnableFeignClients //开启Fegin功能
@EnableCircuitBreaker //开启Hystrix断路器功能
public class ConsumerMovieFeignWithHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieFeignWithHystrixApplication.class, args);
System.out.println("服务消费者启动...");
}
}
7.4.4 HystrxClientFallback.java
//该类作为Hystrix回退使用的类,实现了Feign需要请求的方法
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import org.springframework.stereotype.Component;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/28
* @version 1.0
*/
@Component
public class HystrixClientFallback implements UserFeignClient{
@Override
public User findById(Long id) {
User user = new User();
user.setId(0L);
return user;
}
}
7.4.5 UserFeignClient.java
//在Feign配置类中配置Hystrix的回退机制
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
*
* @title 在Feign类中使用Hystrix的回退机制
* @description
* @author caonanqing
* @createDate 2018/11/9
* @version 1.0
*/
//fallback = HystrixClientFallback.class,fallback是Hystrix的回退机制
//绑定该接口对应的服务,并且使用Hystrix支持回退,访问出现错误时,回退到HystrixClientFallback
@FeignClient(name = "microservice-provider-user", fallback = HystrixClientFallback.class)
public interface UserFeignClient {
// 1.@GetMapping不支持,2.@PathVarible必须要得设置value
@RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id );
}
7.4.6 MovieController.java
package com.keivn.cloud.controller;
import com.keivn.cloud.feign.UserFeignClient;
import com.keivn.cloud.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@RestController
public class MovieController {
@Autowired
private UserFeignClient userFeignClient;
@GetMapping(value = "/movie/{id}")
public User finById(@PathVariable long id ){
return this.userFeignClient.findById(id);
}
}
7.5 Hystrix中Fallback Factory和Fallback
Fallback可以让请求失败时回退,但没有办法知道原因。
Fallback Factory可以让请求失败时回退,并且可以知道原因。
Fallback Factory是Fallback的升级版。它们的配置都是在@FeignClient中配置的。但不能同时使用,会冲突。一般使用Fallback Factory就行了。
7.5.1 Fallback的配置项
// fallback = HystrixClientFallback.class
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/9
* @version 1.0
*/
//fallback = HystrixClientFallback.class,fallback是Hystrix的回退机制
//绑定该接口对应的服务,并且使用Hystrix支持回退,访问出现错误时,回退到HystrixClientFallback
//fallbackFactory是fallback的增强版,fallback与fallbackFactory不能同时使用
@FeignClient(name = "microservice-provider-user",
fallback = HystrixClientFallback.class)
public interface UserFeignClient {
// 1.@GetMapping不支持,2.@PathVarible必须要得设置value
@RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id );
}
7.5.2 Fallback的回退时执行的类
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import org.springframework.stereotype.Component;
/**
*
* @title Fallback回退时执行的方法
* @description
* @author caonanqing
* @createDate 2018/11/28
* @version 1.0
*/
@Component
public class HystrixClientFallback implements UserFeignClient{
@Override
public User findById(Long id) {
User user = new User();
user.setId(0L);
return user;
}
}
7.5.3 Factory的接口类
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/28
* @version 1.0
*/
public interface UserFeignClientWithFactory extends UserFeignClient {
}
7.5.4 Factory的配置项
// fallbackFactory = HystrixClientFactory.class
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/9
* @version 1.0
*/
//fallback = HystrixClientFallback.class,fallback是Hystrix的回退机制
//绑定该接口对应的服务,并且使用Hystrix支持回退,访问出现错误时,回退到HystrixClientFallback
//fallbackFactory是fallback的增强版,fallback与fallbackFactory不能同时使用
@FeignClient(name = "microservice-provider-user",
fallbackFactory = HystrixClientFactory.class)
public interface UserFeignClient {
// 1.@GetMapping不支持,2.@PathVarible必须要得设置value
@RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id );
}
7.5.5 Factory回退时执行的类
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/28
* @version 1.0
*/
@Component
public class HystrixClientFactory implements FallbackFactory<UserFeignClient> {
private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFactory.class);
@Override
public UserFeignClient create(Throwable throwable) {
// HystrixClientFactory.LOGGER.info("fallback; reason was: {}", throwable.getMessage());
// 传统写法
return new UserFeignClientWithFactory() {
@Override
public User findById(Long id) {
User user = new User();
user.setId(-1L);
return user;
}
};
}
}
7.6 Hystrix在Feign的配置类的禁止Hystrix的客户端
7.6.1 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>
<artifactId>microservice-consumer-movie-feign-customizing-without-hystrix</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.kevin.cloud</groupId>
<artifactId>microservice-spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</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-feign</artifactId>
</dependency>
</dependencies>
</project>
7.6.2 application.yml
server:
port: 7901
spring:
application:
name: microservice-consumer-movie-feign-customizing-without-hystrix
eureka:
client:
healthcheck:
enabled: true
service-url:
defaultZone: http://kevin:123456@localhost:8761/eureka
instance:
prefer-ip-address: true
logging: #启动日志
level:
com.keivn.cloud.feign.UserFeignClient: debug
# 解决第一次请求报超时异常的方案:
# hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
# 或者:
# hystrix.command.default.execution.timeout.enabled: false
# 或者:
feign.hystrix.enabled: false # 索性禁用feign的hystrix
# 超时的issue:https://github.com/spring-cloud/spring-cloud-netflix/issues/768
# 超时的解决方案: http://stackoverflow.com/questions/27375557/hystrix-command-fails-with-timed-out-and-no-fallback-available
# hystrix配置: https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.thread.timeoutInMilliseconds
7.6.3 ConsumerMovieFeignCustomizingWithoutHystrixApplication.java
package com.keivn.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
/**
*
* @title 服务消费者
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@SpringBootApplication
@EnableEurekaClient //注册到Eureka
@EnableFeignClients //开启Fegin功能
public class ConsumerMovieFeignCustomizingWithoutHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerMovieFeignCustomizingWithoutHystrixApplication.class, args);
System.out.println("服务消费者启动...");
}
}
7.6.4 Configuration1.java
package com.keivn.config;
import feign.Contract;
import feign.Logger;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;
/**
*
* @title 通过声明额外的配置来控制Feign Client(覆写默认配置)
* @description 为了不与Spring Boot的Application的ComponentScan包冲突,将配置类放到cloud包外面
* @author caonanqing
* @createDate 2018/11/14
* @version 1.0
*/
@Configuration
public class Configuration1 {
// 契约,Contract使用的是Feign本身的注解
@Bean
public Contract feignContract(){
return new feign.Contract.Default();
}
// 启动日志
@Bean
Logger.Level feignLoggerLever(){
return Logger.Level.FULL;
}
}
7.6.5 Configuration2.java
package com.keivn.config;
import feign.Contract;
import feign.Feign;
import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
*
* @title Feign配置类
* @description
* @author caonanqing
* @createDate 2018/11/14
* @version 1.0
*/
@Configuration
public class Configuration2 {
// 直接访问是没有权限的,需要加上该注解配置服务提供者的账号密码。
@Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new BasicAuthRequestInterceptor("kevin","123456");
}
// 该方法是禁用UserFeignClient2的Hystrix
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder(){
return Feign.builder();
}
}
7.6.6 UserFeignClient.java
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import com.keivn.config.Configuration1;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.netflix.feign.FeignClient;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/9
* @version 1.0
*/
@FeignClient(name = "microservice-provider-user", configuration = Configuration1.class
,fallback = HystrixClientFallback.class) //绑定该接口对应的服务,以及配置
public interface UserFeignClient {
// 覆写Feign默认的配置,使用的Feign本身的注解,而不是SpringMVC
@RequestLine("GET /simple/{id}") //GET请求+空格+请求地址
public User findById(@Param("id") Long id );
}
7.6.7 UserFeignClient2.java
package com.keivn.cloud.feign;
import com.keivn.config.Configuration2;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/14
* @version 1.0
*/
//xxx只是随意起的名称,实际是Eureka中Application的名称,url和name必须一起使用
@FeignClient(name = "xxx", url = "http://localhost:8761/", configuration = Configuration2.class
,fallback = UserFeignClient2Fallback.class) //绑定该接口对应的服务,以及配置
public interface UserFeignClient2 {
//访问eureka里注册的服务的名称
@RequestMapping(value ="/eureka/apps/{serviceName}")
public String findServiceInfoFromEurekaByServiceName(@PathVariable("serviceName") String serviceName);
}
7.6.8 HystrixClientFallback.java
package com.keivn.cloud.feign;
import com.keivn.cloud.entity.User;
import org.springframework.stereotype.Component;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/28
* @version 1.0
*/
@Component
public class HystrixClientFallback implements UserFeignClient {
@Override
public User findById(Long id) {
User user = new User();
user.setId(0L);
return user;
}
}
7.6.9 UserFeignClient2Fallback.java
package com.keivn.cloud.feign;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/28
* @version 1.0
*/
public class UserFeignClient2Fallback implements UserFeignClient2{
@Override
public String findServiceInfoFromEurekaByServiceName(String serviceName) {
return "userFignClient2";
}
}
7.6.10 MovieController.java
package com.keivn.cloud.controller;
import com.keivn.cloud.feign.UserFeignClient;
import com.keivn.cloud.entity.User;
import com.keivn.cloud.feign.UserFeignClient2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@RestController
public class MovieController {
@Autowired
private UserFeignClient userFeignClient;
@Autowired
private UserFeignClient2 userFeignClient2;
@GetMapping(value = "/movie/{id}")
public User finById(@PathVariable long id ){
return this.userFeignClient.findById(id);
}
@GetMapping("/{serviceName}")
public String findServiceInfoFromEurekaByServiceName(@PathVariable String serviceName){
return this.userFeignClient2.findServiceInfoFromEurekaByServiceName(serviceName);
}
}
7.6.11 User.java
package com.keivn.cloud.entity;
import java.io.Serializable;
import java.math.BigDecimal;
/**
*
* @title
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
public class User implements Serializable {
private Long id;
private String username;
private String name;
private Short age;
private BigDecimal balance;
public User() {
}
public User(Long id, String username, String name, Short age, BigDecimal balance) {
this.id = id;
this.username = username;
this.name = name;
this.balance = balance;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Short getAge() {
return age;
}
public void setAge(Short age) {
this.age = age;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
7.7 Hystrix Dashboard(监控器)
Hystrix Dashboard主要用来监控Hystrix的各项指标信息。 支持三种不同的监控方式: 1.默认的集群监控:通过URL:http://hostname:port/turbine/turbine.stream开启,实现对默认集群的监控。(Dashboard+Turbine结合使用) 2.指定的集群监控:通过URL:http://hostname:port/turbine/turbine.stream?cluster=[clusterName]开启,实现对clusterName集群的监控。(Dashboard+Turbine结合使用) 3.单体应用的监控:通过URL:http://hystrix-app:port/hystrix.stream开启,实现对具体某个服务实例的监控。(Dashboard使用) Delay:控制服务器上轮询监控信息的延迟时间,默认为2000毫秒,可以通过配置该属性来降低客户端的网络和CPU消耗。 Title:该参数可以展示合适的标题。
7.7.1 pom.xml
<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>
<artifactId>microservice-hystrix-dashboard</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.kevin.cloud</groupId>
<artifactId>microservice-spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
</dependencies>
</project>
7.7.2 application.yml
server:
port: 8030
7.7.3 HystrixDashboardApplication.java
package com.kevin.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
/**
*
* @title Hystrix Dashboard主要用来监控Hystrix的各项指标信息
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@SpringBootApplication //设为springboot
@EnableHystrixDashboard //启用Hystrix Dashboard功能
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
System.out.println("HystrixDashboard启动...");
}
}
7.8 Hystrix Turbine(集群监控器)
只使用Hystrix Dashboard时只能对单体应用进行监控,对实际生产环境中作用不大,因为实际中都是集群模式。
使用Turbine和Dashboard结合起来可以对集群进行监控。
使用Hystrix Turbine比较简单,只需要引入依赖和加上注解和配置就可以了。
7.8.1 pom.xml
// spring-cloud-starter-turbine加入其依赖,如果不行,再加入spring-cloud-netflix-turbine
<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>
<artifactId>microservice-hystrix-turbine</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.kevin.cloud</groupId>
<artifactId>microservice-spring-cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
</dependencies>
</project>
7.8.2 application.yml
server:
port: 8031
spring:
application:
name: microservice-hystrix-turbine
eureka:
client:
serviceUrl:
defaultZone: http://kevin:123456@localhost:8761/eureka
instance:
prefer-ip-address: true
turbine:
aggregator:
#指定聚合哪些集群,对应需要使用Turbine的服务名称,想使用全部可以使用default,想使用多个的时候用","分隔,可以使用http://hostname:port/turbine/turbine.stream?cluster=[clusterName]开启
clusterConfig: default
#对应的服务的名称,表明监控哪些服务
appConfig: microservice-consumer-movie-ribbon-with-hystrix,microservice-consumer-movie-feign-with-hystrix
clusterNameExpression: "'default'"
#1.clusterNameExpression指定集群名称,默认表达式appName,对应turbine.aggregator.clusterConfig需要配置监控的服务名称
#2.clusterNameExpression: "'default'",对应turbine.aggregator.clusterConfig:default,但可以不写,因为默认就是default
#3.clusterNameExpression:metadata['cluster']时,如果监控的服务配置了eureka.instance.metadata-map.cluster:xxx,则Turbine配置文件需要turbine.aggregator.clusterConfig:xxx
7.8.3 HystrixTurbineApplication.java
// 在启动类加上注解@EnableTurbine,开启Trurbine服务,其中@EnableTurbine注解中包含了@EnableDiscoveryClient,即注册服务
package com.kevin.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.turbine.EnableTurbine;
/**
*
* @title Hystrix Dashboard主要用来监控Hystrix的各项指标信息
* @description
* @author caonanqing
* @createDate 2018/11/7
* @version 1.0
*/
@SpringBootApplication //springboot启动类
@EnableTurbine //hystrix的Turbine监控器
public class HystrixTurbineApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixTurbineApplication.class, args);
System.out.println("HystrixTurbine启动...");
}
}
7.8.4 演示监控器
1.启动ZurekaServer注册中心
2.启动Provider服务提供者
3.启动需要监控的Ribbon的Hystrix和Feign Hystrix
4.启动Hystrix Dashboard
5.启动Hystrix Turbine