zoukankan      html  css  js  c++  java
  • SpringCloud中使用Hystrix

    1.  引言


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

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

    2.  服务搭建


    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">
        <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;
    
    @RestController
    @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">
        <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;
    
    @EnableCircuitBreaker
    @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 {
        @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;
    
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserClient userClient;
    
        @RequestMapping("/hello")
        public String hello() {
            return userClient.sayHello();
        }
    
    }

    目录结构

    3.  演示


    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本身设计就不是用来做这个事情的,它设计是用来阻止级联失败,用快速失败来代替请求排队的,但是有了客户端负载均衡器以后,当其中一台机器挂了以后,请求会转发到其它机器上。因此,切换是负载均衡器做的,跟断路器没有关系)

    4.  小结


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

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

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

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

    5.  其它


    Feign Hystrix Fallbacks

    Hystrix介绍

    Hystrix是如何工作的

    Spring Boot 集成 Hystrix

    SpringCloud学习笔记(3)——Hystrix

    SpringCloud学习笔记(2)——Ribbon

    SpringCloud学习笔记(1)——Eureka

  • 相关阅读:
    topcoder srm 681 div1
    topcoder srm 683 div1
    topcoder srm 684 div1
    topcoder srm 715 div1
    topcoder srm 685 div1
    topcoder srm 687 div1
    topcoder srm 688 div1
    topcoder srm 689 div1
    topcoder srm 686 div1
    topcoder srm 690 div1 -3
  • 原文地址:https://www.cnblogs.com/cjsblog/p/9687458.html
Copyright © 2011-2022 走看看