SpringCloud中使用Hystrix

  • 引言
  • 一般而言,一个服务都是部署了多台机器的,那么在这种情况下,当其中一个服务挂了以后Hystrix是怎么处理的呢?

    为了验证这个问题,我们准备两个服务:user-api 和 app-gateway,再加一个Eureka Server

    1. 服务搭建

    2.1. 注册中心

    关于这一部分,参见《SpringCloud学习笔记(1)——Eureka》

    2.2. 服务提供方

    复制代码
    <?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"&gt;
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cjs.example</groupId>
    <artifactId>user-api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <name>user-api</name>
    <description></description>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>
    
    <dependencies>
        <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-actuator</artifactId>
        </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>
    复制代码
    复制代码
    server:
    port: 8081
    spring:
    application:
    name: user-api

    eureka:
    instance:
    instance-id: 192.168.1.1:${server.port}
    hostname: 192.168.1.1
    client:
    service-url:
    defaultZone: http://192.168.1.1:8761/eureka/
    复制代码
    复制代码
    package com.cjs.example;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestControllerbr/>@SpringBootApplication
    public class UserApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserApiApplication.class, args);
    }
    
    @RequestMapping("/sayHello")
    public String sayHello() {
        System.out.println("lalala");
        return "hello";
    }

    }
    复制代码
    这里通过控制打印日志来观察调用的是哪个机器上的该服务

    2.3. 服务消费方

    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"&gt;
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cjs.example</groupId>
    <artifactId>app-gatewate</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <name>app-gatewate</name>
    <description></description>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>
    
    <dependencies>
        <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-openfeign</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-actuator</artifactId>
        </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>
    复制代码
    application.yml

    复制代码
    server:
    port: 8080
    spring:
    application:
    name: app-gateway
    eureka:
    instance:
    instance-id: 192.168.1.1:${server.port}
    hostname: 192.168.1.1
    client:
    service-url:
    defaultZone: http://192.168.1.1:8761/eureka/
    feign:
    hystrix:
    enabled: true
    复制代码
    AppGatewayApplication.java

    复制代码
    package com.cjs.example;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.openfeign.EnableFeignClients;

    @EnableCircuitBreakerbr/>@EnableFeignClients
    @SpringBootApplication
    public class AppGatewayApplication {

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

    }
    复制代码
    FeignClient

    复制代码
    package com.cjs.example.service;

    import com.cjs.example.fallback.UserClientFallback;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.RequestMapping;

    @FeignClient(value = "user-api", fallback = UserClientFallback.class)
    public interface UserClient {

    @RequestMapping("/sayHello")
    String sayHello();

    }
    复制代码
    Hystrix

    复制代码
    package com.cjs.example.fallback;

    import com.cjs.example.service.UserClient;
    import org.springframework.stereotype.Component;

    @Component
    public class UserClientFallback implements UserClient {br/>@Override
    public String sayHello() {
    return "Oh! Error!!!";
    }
    }
    复制代码
    UserController.java

    复制代码
    package com.cjs.example.controller;

    import com.cjs.example.service.UserClient;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestControllerbr/>@RequestMapping("/user")
    public class UserController {

    @Autowired
    private UserClient userClient;
    
    @RequestMapping("/hello")
    public String hello() {
        return userClient.sayHello();
    }

    }
    复制代码
    目录结构

    1. 演示

    1、依次启动各服务:eureka-demo-server,user-api(两台),app-gateway

    2、浏览器查看 http://192.168.1.1:8761/

    3、通过请求 http://localhost:8080/user/hello 令app-gateway调用user-api服务(使用FeignClient调用,并集成Hystrix)

    4、观察控制打印“lalala”,同时页面输出“hello”

    5、停掉其中一台user-api,发现在短时间内会执行回退操作(即页面返回“Oh! Error!!!”),随后恢复正常(因为请求打到另一台机器上了)

    由此,可以看出

    首先,一般Hystrix 和 Ribbon一起使用的,而且必要有注册中心,在这种情况下,如果调用某个服务失败(或者拒绝、超时等),会尝试调用其它机器上的该服务,但这种切换需要一定的时间,并不是无缝切换的(也就是说,并不是在服务调用失败或拒绝的时候理解换到另一台机器,在所有机器都尝试过以后都失败的情况下才执行回退逻辑,不是这样的,可以想象一下,单纯依靠Hystrix的能力是不能做到这一点的,况且,Hystrix本身设计就不是用来做这个事情的,它设计是用来阻止级联失败,用快速失败来代替请求排队的,但是有了客户端负载均衡器以后,当其中一台机器挂了以后,请求会转发到其它机器上。因此,切换是负载均衡器做的,跟断路器没有关系)

    1. 小结

    Ribbon是一个客户端的负载均衡器,它决定选择哪一台机器来调用

    Hystrix是一个断路器,它将服务调用进行隔离,用快速失败来代替排队,阻止级联调用失败。它的目的是不让服务挂掉。

    二者之间没有关系,因为设计它们的目的不一样,解决的问题也不一样

    再回到开头提到的问题,即使没有Hystrix,一台机器挂掉以后,后续的请求也会转到其它机器上。只是有了Hystrix以后,遇到这种失败的时候会执行回退操作。

    原文地址:http://blog.51cto.com/13954634/2178828

    时间: 2024-11-05 20:36:56

    SpringCloud中使用Hystrix的相关文章

    Springcloud 中 SpringBoot 配置全集 (收藏版)

    Springcloud 中 SpringBoot 配置全集 (收藏版) 疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Springcloud 高并发系列文章,将为大家介绍三个版本的 高并发秒杀: 一.版本1 :springcloud + zookeeper 秒杀 二.版本2 :springcloud + redis 分布式锁秒杀 三.版本3 :springcloud + Nginx + Lua 高性能版本秒杀 以

    springcloud中servcie层调用fegin异常以及异步方法的实现

    近日在做业务上的短信推送和APP消息推送,通过调用别的模块的接口来实现,在springcloud中通过fegin进行调用.这里要说明的事情并不是如何开发推送功能,而是在调试过程中碰到的一些小问题.我把消息推送之前的业务处理代码以及调用推送服务的代码都放在方法pushByAppAndShortMessage()中,然后把这个方法单独的放在crmservice里面.由于业务处理,pushByAppAndShortMessage中需要用到别的service,就不得不在crmservice中进行大量的a

    Springcloud中的region和zone的使用

    Springcloud中的region和zone的使用 一.背景 用户量比较大或者用户地理位置分布范围很广的项目,一般都会有多个机房.这个时候如果上线springCloud服务的话,我们希望一个机房内的服务优先调用同一个机房内的服务 ,当同一个机房的服务不可用的时候,再去调用其它机房的服务,以达到减少延时的作用. 二.概念 eureka提供了region和zone两个概念来进行分区,这两个概念均来自于亚马逊的AWS: (1)region:可以简单理解为地理上的分区,比如亚洲地区,或者华北地区,再

    SpringCloud 进阶之Hystrix(断路器)

    1. Hystrix 断路器 Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败, 比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分 布式系统的弹性; "断路器"本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方 返回一个符合预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就

    解决:SpringCloud中Feign支持GET请求POJO传参

    在日常的开发中,当遇到一个请求需要传递多个参数时,我们习惯将参数封装到一个POJO对象中,已提高程序的可读性和简化编写.但是在使用SpringCloud时,Feign对SpringMVC注解支持并不完善,其中一点就是,当发送的GET请求携带多个参数时,不能使用POJO来封装参数,这个就比较蛋疼了.一种使之支持GET请求POJO传递参数的方法如下: 添加Maven依赖 <dependency> <groupId>org.springframework.cloud</groupI

    SpringCloud学习系列-Hystrix断路器(2)

    服务熔断 1.是什么 服务熔断熔断机制是应对雪崩效应的一种微服务链路保护机制.当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回"错误"的响应信息.当检测到该节点微服务调用响应正常后恢复调用链路.在SpringCloud框架里熔断机制通过Hystrix实现.Hystrix会监控微服务间调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制.熔断机制的注解是@HystrixCommand. 2.实验代码   1.

    基于springcloud搭建项目-Hystrix篇(五)

    1.概述 (1).首先要知道分布式系统面临的问题复杂分布式体系结构中应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败 (2).服务雪崩 多个服务之间相互调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这既是所谓的“扇出”.如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的嗲用就会占用原来越多的系统资源,今儿引起系统崩溃,所谓的“雪崩效应”. (3).对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒

    SpringCloud Feign对Hystrix(断路由)的支持

    第一步:首先开启Feign对Hystrix的支持,在properties文件中添加以下配置: feign.hystrix.enabled=true. 第二步:在上一篇Feign的基础上添加Hystrix(断路由) @FeignClient(name = "这里写服务名称",fallback = "UserServiceHystrix.class")public interface UserServiceAPI { @RequestMapping(value = &q

    Feign中使用hystrix

    一.在Order工程中的bootstrap.yml中增加配置 feign: hystrix: enabled: true 原文地址:https://www.cnblogs.com/linlf03/p/10398592.html