5.断路器(Hystrix)

来源:互联网 发布:stc15单片机视频教程 编辑:程序博客网 时间:2024/04/27 18:41

1.Hystrix介绍

(1)在微服务中,单个服务为了高可用性防止单点故障通常会集群部署。由于网路或其他原因服务变得不可用时服务调用者会出现长等待的线程阻塞,此时会有大量的其他请求涌入,servlet容器线程资源会被消耗完毕。服务之间有依赖性,于是会出现故障传播引起雪崩效应,断路器就是为了解决这样的问题。

(2)在服务与用户之间通过api进行交互,用户调用api消费服务,当某个服务不可用(有一个时间阈值)时断路器就会打开,同时为这个服务的调用者返回一个固定的值。简单来说就是为服务的瘫痪做一个保险,防止用户得不到服务返回结果而阻塞等待进而影响其他服务和用户。

(3)当hystrix检测到服务不可用时,会自动断开不可用服务,具体的就是每次消费者调用方法都不再去访问服务提供者,而是直接返回一个设定好的固定值。当服务再次可用时在打开服务,同时允许消费者调用方法再去访问服务提供者。如果hystrix打开服务如何知道服务可用呢?hystrix允许额外发送一些请求到服务提供者检测服务是否可用。


2.启动eureka注册服务/启动一个服务提供者

cmd下用jar包方式启动

访问localhost:8761查看是否正常启动


3.创建一个消费者工程(在ribbon中使用hystrix)

这里在上一个消费者(ribbon)工程中改造
加入hystrix依赖
        <!-- hystrix -->        <dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-hystrix</artifactId></dependency>
(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>  <groupId>com.tyf</groupId>  <artifactId>ribbon_test</artifactId>  <version>0.0.1-SNAPSHOT</version>  <packaging>jar</packaging>  <name>ribbon_test</name>  <url>http://maven.apache.org</url>  <!-- springboot -->  <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>1.5.2.RELEASE</version>        <relativePath/>   </parent>  <!-- 编码 -->  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>  <!-- springcloud -->  <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-eureka</artifactId>        </dependency>        <!-- ribbon -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-ribbon</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency><!-- test -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <!-- hystrix -->        <dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-hystrix</artifactId></dependency>  </dependencies>    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>Dalston.RC1</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>    <!-- maven插件 -->    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>            <repositories>        <repository>            <id>spring-milestones</id>            <name>Spring Milestones</name>            <url>https://repo.spring.io/milestone</url>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>    </repositories>  </project>
启动类中加入注解@EnableCircuitBreaker开启断路器(有博客说加@EnableHystrix,我试了但是服务明明调用了但是消费端仍然显示服务不可用)
(2)启动类
package com.tyf.ribbon_test;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.hystrix.EnableHystrix;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;/* *1.@SpringBootApplication: *2.@EnableDiscoveryClient:向服务中心注册 *3.@Bean:向程序ioc中注入一个bean(方法返回值就是这个bean) *4.@LoadBalanced:方法开启负载均衡功能 *5.restTemplate(): * * */@SpringBootApplication@EnableDiscoveryClient@EnableHystrixpublic class App {public static void main(String[] args) {        SpringApplication.run(App.class, args);    }    @Bean    @LoadBalanced    RestTemplate restTemplate() {        return new RestTemplate();    }}

service方法(这个方法远程调用别人的服务)中加@HystrixCommand注解为方法创建调用失败的保险,fallbackMethod指定失败需要调用的方法
(3)service
package com.tyf.ribbon_test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;/* * 1.@Service: * 2.@Autowired:向ioc获取一个bean * 3.RestTemplate restTemplate: * 这个bean是启动类中注入ioc的一个bean * 通过其getForObject发送请求调用服务方法 * (同一个服务的多个实例提供了负载均衡的功能) * 4.http://eureks-serverProvider-test/helloWorld/test: * 使用服务的名称来调用服务,后面是服务的@RequestMapping地址 *  *  */@Servicepublic class modelService {@Autowired    RestTemplate restTemplate;@HystrixCommand(fallbackMethod = "testConsumerError")    public String testConsumer() {    //使用服务名称访问服务        return restTemplate.getForObject("http://eureks-serverProvider-test/helloWorld/test",String.class);    }//这个方法与testConsumer方法参数和返回值应该是一样的public String testConsumerError(){return "服务不可用!";}}
其他不变
(4)controller
package com.tyf.ribbon_test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;/* *  * 访问地址:http://localhost:8765/modelController/test *  */@RestController@RequestMapping("/modelController")public class modelController {@AutowiredmodelService model_service;    @RequestMapping(value="/test",method = RequestMethod.GET)    public void test(){    System.out.println(model_service.testConsumer());    }}

(5)resources/application.yml
eureka:  client:    serviceUrl:      defaultZone: http://localhost:8761/eureka/server:  port: 8765spring:  application:    name: ribbon_serverConsumer_test
(6).启动消费者工程,查看是否正常启动,两次访问消费者


浏览器访问消费者(http://localhost:8765/modelController/test),先后两次访问,第二次关闭服务提供者


4.创建消费者工程(feign中使用hystrix)

使用上一个feign消费者工程中改
feign自带hystrix功能,低版本springcloud没有自动打开,需要在配置文件中添加打开(feign:hystrix:enabled:true)
(1)resources/application.yml
eureka:  client:    serviceUrl:      defaultZone: http://localhost:8761/eureka/server:  port: 8766feign:  hystrix:    enabled: truespring:  application:    name: feign-consumer-test


service接口的@FeignClient注解中使用fallback参数指定一个新建的类
(2)service接口
package com.tyf.feign_test;import org.springframework.cloud.netflix.feign.FeignClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;/* *   消费者service(用接口调用别人的controller来代替自己的service) * 1.@FeignClient:指定想要调用的服务提供者的名称 * 2.@RequestMappin:服务提供者程序中的一个具体url映射(服务提供者一个控制器下面的某个具体方法) * 3.@RequestParam: * 拼接起来就是:http://eureks-serverProvider-test/helloWorld/test?name=xxx */@FeignClient(value = "eureks-serverProvider-test",fallback=modelServiceError.class)public interface modelService {@RequestMapping(value = "/helloWorld/test",method = RequestMethod.GET)    String consumerTest(@RequestParam(value = "name") String name);}

fallback类,需要实现上面的service接口,并使用@Component注入到ioc中。service接口调用失败就会调用这个类相对应的方法
(3)fallback类
package com.tyf.feign_test;import org.springframework.stereotype.Component;@Componentpublic class modelServiceError implements modelService {@Overridepublic String consumerTest(String name) {return "服务不可用";}}
其他不变
(4)controller
package com.tyf.feign_test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;/* * 消费者控制器: *  * 1.modelService:持有一个接口service,调用接口的方法(真正调用的是别人提供的方法) *  * 2.访问url:http://localhost:8766/feignConsumer/test?name=xxx *  * 3.参数name传给接口方法,再传给服务提供者(controller传给service计算得到结果) *       服务提供者将计算结果返回给本地(先返回给本地service接口再返回给本地controller) *  */@RestController@RequestMapping("/feignConsumer")public class modelController {@Autowired    modelService model_service;    @RequestMapping(value = "/test",method = RequestMethod.GET)    public void test(@RequestParam String name){        System.out.println(model_service.consumerTest(name));    }}
(5)启动类
package com.tyf.feign_test;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.feign.EnableFeignClients;/** * 启动类 * 1.@SpringBootApplication: * 2.@EnableDiscoveryClient: * 3.@EnableFeignClients:开启feign功能 * */@SpringBootApplication@EnableDiscoveryClient@EnableFeignClientspublic class App {public static void main(String[] args) {        SpringApplication.run(App.class, args);    }}
(6)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>  <groupId>com.tyf</groupId>  <artifactId>feign_test</artifactId>  <version>0.0.1-SNAPSHOT</version>  <packaging>jar</packaging>  <name>feign_test</name>  <url>http://maven.apache.org</url>  <!-- 1 -->  <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>1.5.2.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->  </parent>  <!-- 2 -->  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>  <!-- 3 --><dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-eureka</artifactId>        </dependency>        <!-- 4 -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-feign</artifactId>        </dependency>        <!-- 5 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency><!-- 6 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>  </dependencies>    <!-- 7 -->  <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>Dalston.RC1</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>      <!-- 8 -->  <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>  </build>    <!-- 9 -->  <repositories>        <repository>            <id>spring-milestones</id>            <name>Spring Milestones</name>            <url>https://repo.spring.io/milestone</url>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>  </repositories>    </project>

(7)启动消费者,浏览器多次访问消费者(第二次关闭服务提供者)


5.Hystrix仪表板

在第一个消费者(Ribbon+Hystrix)中改造
加入依赖
<dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-actuator</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>        </dependency>
(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>  <groupId>com.tyf</groupId>  <artifactId>ribbon_test</artifactId>  <version>0.0.1-SNAPSHOT</version>  <packaging>jar</packaging>  <name>ribbon_test</name>  <url>http://maven.apache.org</url>  <!-- springboot -->  <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>1.5.2.RELEASE</version>        <relativePath/>   </parent>  <!-- 编码 -->  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  </properties>  <dependencies>  <!-- springcloud -->  <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-eureka</artifactId>        </dependency>        <!-- ribbon -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-ribbon</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency><!-- test -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <!-- hystrix -->        <dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-starter-hystrix</artifactId></dependency><!-- 仪表盘依赖1 --><dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-actuator</artifactId>        </dependency><!-- 仪表盘依赖2 -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>        </dependency>  </dependencies>    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>Dalston.RC1</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>    <!-- maven插件 -->    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build>            <repositories>        <repository>            <id>spring-milestones</id>            <name>Spring Milestones</name>            <url>https://repo.spring.io/milestone</url>            <snapshots>                <enabled>false</enabled>            </snapshots>        </repository>    </repositories>  </project>
启动类加入@EnableHystrixDashboard和@EnableHystrix注解开启仪表盘
(2)启动类
package com.tyf.ribbon_test;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;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.hystrix.EnableHystrix;import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;/* *1.@SpringBootApplication: *2.@EnableDiscoveryClient:向服务中心注册 *3.@Bean:向程序ioc中注入一个bean(方法返回值就是这个bean) *4.@LoadBalanced:方法开启负载均衡功能 *5.restTemplate(): *6.@EnableHystrixDashboard:开启仪表盘 * */@EnableHystrix@SpringBootApplication@EnableDiscoveryClient@EnableCircuitBreaker@EnableHystrixDashboardpublic class App {public static void main(String[] args) {        SpringApplication.run(App.class, args);    }    @Bean    @LoadBalanced    RestTemplate restTemplate() {        return new RestTemplate();    }}
(3)其他不变,启动消费者,访问http://localhost:8765/hystrix

Cluster via Turbine:集群服务(默认)Single Hystrix App:单个hystrix的程序(就是我们这里的消费者工程)

http://localhost:8765/hystrix.stream(访问本消费者工程下面的hystrix.stream)点击按钮进入页面



(4)查看仪表板


原创粉丝点击