使用Hystrix实现微服务的容错处理

使用Hystrix实现微服务的容错处理

至此,已用Eureka实现类微服务的注册与发现,Ribbon实现了客户端侧的负载均衡,Feign实现了声明式的API调用。

实现容错的手段

如果服务提供者响应非常缓慢,那么消费者对提供者的请求就会被强制等待,直到提供者响应或超时。在高负载场景下,如果不做任何处理,此类问题可能会导致服务消费者的资源耗尽甚至整个系统的崩溃。例如,曾经发生过一个案例——某电子商务网站在一个黑色星期五发生过载。过多的并发请求,导致用户支付的请求延迟很久都没有响应,在等待很长时间后最终失败。支付失败又导致用户重新刷新页面并再次尝试支付,进一步增加了服务器的负载,最终整个系统都崩溃了。

雪崩效应

微服务架构的应用系统通常包含多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,微服务之间难免存在依赖关系。我们知道,任何微服务都并非100%可用,网络往往也很脆弱,因此难免有些请求会失败。
我们通常把“基础服务故障”导致“级联故障”的现象称为雪崩效应。雪崩效应描述的是提供者不可用导致消费者不可用,并将不可用逐渐放大的过程。

如何容错

要想防止雪崩效应,必须有一个强大的容错机制。该容错机制需实现以下两点。

  • 为网络请求设置超时:必须为网络请求设置超时。正常情况下,一个远程调用一般在几十毫秒内就能得到响应了。如果依赖的服务不可用或者网络有问题,那么响应时间就会变得很长(几十秒)。通常情况下,一次远程调用对应一个线程/进程。如果响应太慢,这个线程/进程就得不到释放。而线程/进程又对应着系统资源,如果得不到释放的线程/进程越积越多,资源就会逐渐耗尽,最终导致服务的不可用。因此,必须为每个网络请求设置超时,让资源尽快释放。
  • 使用断路器模式:如果对某个微服务的请求有大量的超时(常常说明该微服务不可用),再去让新的请求访问该服务已经没有任何意义,只会无谓消耗资源。例如,设置了超时时间为1s,如果短时间内有大量的请求无法在1s内得到响应,就没有必要再去请求依赖的服务了。
    断路器可理解为容易导致错误的操作的代理。这种代理能够统计一段时间内调用失败的次数,并决定是正常请求依赖的服务还是直接返回。
    断路器也可以辅助诊断依赖的服务是否已经恢复正常。如果发现依赖的服务已经恢复正常,那么就会恢复请求该服务。使用这种方式,就可以实现微服务的"自我修复"——当依赖的服务不正常时,打开断路器时快速失败,从而防止雪崩效应;当发现依赖的服务恢复正常时,又会恢复请求。

断路器状态转换的逻辑

  • 正常请求下,断路器关闭,可正常请求依赖的服务。
  • 当一段时间内,请求失败率达到一定阈值(例如错误率达到50%,或100次/分钟等),断路器就会打开。此时,不会再去请求依赖的服务。
  • 断路器打开一段时间后,会自动进入"半开"状态。此时,断路器可允许一个请求访问依赖的服务。如果该请求能够调用成功,则关闭断路器;否则继续保持打开状态。

使用Hystrix实现容错

Hystrix简介

Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。

  • 包裹请求:使用HystrixCommand包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用了设计模式中的"命令模式"。
  • 跳闸机制:当某服务的错误率超过一定阈值时,Hystrix开源自动或手动跳闸,停止请求该服务一段时间。
  • 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就会被立即拒绝,而不是排队等待,从而加速失败判定。
  • 监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时和被拒绝的请求等。
  • 回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
  • 自我修复:断路器打开一段时间后,会自动进入”半开状态“。

通用方式整合Hystrix

在Spring Cloud中,整合Hystrix非常方便。以项目microservice-consumer-movie-ribbon为例,我们来为它整合Hystrix。
1)复制项目microservice-consumer-movie-ribbon,将ArtifactId修改为microservice-comsumer-movie-ribbon-hystrix。
2)为项目添加以下依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

3)在启动类上添加注解@EnableCircuitBreaker或@EnableHystrix,从而为项目启用断路器支持。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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;

@SpringBootApplication
@EnableHystrix
public class MicroserviceConsumerMovieRibbonHystrixApplication {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

4)修改MovieController,让其中的findById方法具备容错能力。

package com.example.controller;

import com.example.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 java.util.List;

@RestController
public class MovieController {
    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "findByIdFallback")
    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id){
        return this.restTemplate.getForObject("http://microservice-provider-user/"+id,User.class);
    }

    public User findByIdFallback(Long id){
        User user = new User();
        user.setId(-1L);
        user.setName("默认用户");
        return user;
    }
}

由代码可知,为findById方法编写了一个回退方法findByIdFallback,该方法与findById方法具有相同的参数与返回值类型,该方法返回了一个默认的User。
在findById方法上,使用注解@HystrixCommand的fallbackMethod属性,指定回退方法是findByIdFallback。注解@HystrixCommand由名为javanica的Hystrix contrib库提供。javanica是一个Hystrix的子项目,用于简化Hystrix的使用。Spring Cloud自动将Spring bean与该注解封装在一个连接到Hystrix断路器的代理中。

@HystrixCommand的配置非常灵活,可使用注解@HystrixProperty的commandProperties属性来配置@HystrixCommand。
测试
1)启动项目microservice-discovery-eureka。
2)启动项目microservice-provider-user。
3)启动项目microservice-consumer-movie-ribbon-hystrix。
4)访问http://localhost:8010/user/1,可获得如下结果
在这里插入图片描述
5)停止microservice-provider-user

在这里插入图片描述
6)再次访问http://localhost:8010/user/1
在这里插入图片描述
我们知道,当请求失败、被拒绝、超时或者断路器打开时,都会进入回退方法。但进入回退方法并不意味着断路器已经被打开。那么,如何才能明确了解断路器当前的状态?
在很多场景下,我们需要获得造成回退的原因,只需在falllback方法上添加一个Throwable参数即可。

package com.example.controller;

import com.example.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 java.util.List;

@RestController
public class MovieController {
    private static final Logger LOGGER=LoggerFactory.getLogger(MovieController.class);
    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "findByIdFallback")
    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id){
        return this.restTemplate.getForObject("http://microservice-provider-user/"+id,User.class);
    }

    public User findByIdFallback(Long id,Throwable throwable){
        LOGGER.error("进入回退方法,异常:",throwable);
        User user = new User();
        user.setId(-1L);
        user.setName("默认用户");
        return user;
    }
}

在这里插入图片描述
多数场景下,当发生业务异常时,我们并不想触发fallback。此时要怎么办呢?Hystrix有个HystrixBadRequestException类,这是一个特殊的异常类,当该异常发生时,不会触发回退。因此,可将自定义的业务异常继承该类,从而达到业务异常不回退的效果。
另外,@HystrixCommand为我们提供了ignoreExceptions属性,也可借助该属性来配置不想执行回退的异常类。


    @HystrixCommand(fallbackMethod = "findByIdFallback",ignoreExceptions = {IllegalArgumentException.class, HystrixTimeoutException.class})
    @GetMapping("/user/{id}")
    public User findById(@PathVariable Long id){
        return this.restTemplate.getForObject("http://microservice-provider-user/"+id,User.class);
    }

这样,即使在findById中发生IllegalArgumentException或者HystrixTimeoutException,也不会执行findByIdFallback方法。

Hystrix断路器的状态监控与深入理解

引入Spring Boot Actuator

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

关闭安全管理,让health显示更多内容

management:
  security:
    enabled: false

断路器的状态也会暴露在Actuator提供的/health端点中,这样就可以直观地了解断路器的状态。
测试
1)启动项目microservice-discovery-eureka。
2)启动项目microservice-provider-user。
3)启动项目microservice-consumer-movie-ribbon-hystrix。
4)访问http://localhost:8010/user/1,可正常获得结果。
5)访问http://localhost:8010/health,可获得类似如下的结果。
在这里插入图片描述

		"eureka": {
			"description": "Remote status from Eureka server",
			"status": "UP",
			"applications": {
				"MICROSERVICE-CONSUMER-MOVIE": 1,
				"MICROSERVICE-PROVIDER-USER": 1
			}
		}

6)停止microservice-provider-user,再次访问
在这里插入图片描述
在这里插入图片描述

		"eureka": {
			"description": "Remote status from Eureka server",
			"status": "UP",
			"applications": {
				"MICROSERVICE-CONSUMER-MOVIE": 1,
				"MICROSERVICE-PROVIDER-USER": 1
			}
		}

我们发现尽管执行了回退逻辑,返回了默认用户,但此时Hystrix的状态依然是UP,这是因为我们失败率还没有达到阈值(默认是5s内20次失败)
8)持续快速的访问http://locahost:8010/user/1,直到请求快速返回。再次查看状态。
在这里插入图片描述

在这里插入图片描述

	"hystrix": {
		"status": "CIRCUIT_OPEN",
		"openCircuitBreakers": ["MovieController::findById"]
	}

Hystrix线程隔离策略与传播上下文

Hystrix的隔离策略有两种:分别是线程隔离和信号量隔离。

  • THREAD(线程隔离):使用该方式,HystrixCommand将在单独的线程上执行,并发请求受到线程池中的线程数量的限制。
  • SEMAPHORE(信号量隔离):使用该方法,HystrixCommand将在调用线程上执行,开销相对较小,并发请求受到信号量个数的限制。
    Hystrix中默认并且推荐使用线程隔离(THREAD),因为这种方式有一个除网络超时以外的额外保护层。
    一般来说,只有当调用负载非常高时(例如每个实例每秒调用数百次)才需要使用信号量隔离,因为在这种场景下使用THREAD开销会比较高。信号量隔离一般仅适用于非网络调用的隔离。
    可使用execution.isolation.strategy属性指定隔离策略。

Feign使用Hystrix

前文是使用注解@HystrixCommand的fallbackMethod属性实现回退的。然而,Feign是以接口形式工作的,它没有方法体,前文讲解的方式显然不适用于Feign。
在Spring Cloud中,为Feign添加回退更加简单。事实上,Spring Cloud默认已为Feign整合了Hystrix,要想为Feign打开Hystrix支持,只需设置feign.hystrix.enabled=true

为Feign添加回退

1)复制项目microservice-consumer-movie-feign,将ArtifactId修改为microservice-consumer-movie-feign-hystrix-fallback。

2)在application.yml中添加feign.hystrix.enable: true,从而开启Feign的Hystrix支持。

feign:
  hystrix:
    enabled: true

3)将之前编写的Feign接口修改成如下内容

package com.example.feign;

import com.example.entity.FeignClientFallback;
import com.example.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name = "microservice-provider-user",fallback = FeignClientFallback.class)
public interface UserFeignClient {
    @RequestMapping(value = "/{id}",method = RequestMethod.GET)
    public User findById(@PathVariable("id") Long id);
}
package com.example.entity;

import com.example.feign.UserFeignClient;
import org.springframework.stereotype.Component;

@Component
public class FeignClientFallback implements UserFeignClient {
    @Override
    public User findById(Long id){
        User user = new User();
        user.setId(-1L);
        user.setUsername("默认用户");
        return user;
    }
}

测试
1)启动项目microservice-discovery-eureka。
2)启动项目microservice-provider-user。
3)启动项目microservice-consumer-movie-feign-hystrix-fallback。
4)访问http://localhost:8010/user/1,可正常获得结果。
在这里插入图片描述

5)停止microservice-provider-user。
6)再次访问http://localhost:8010/user/1
在这里插入图片描述
在Spring Cloud Dalston之间的版本中,Feign默认已开启Hystrix支持,无须设置feign.hystrix.enabled=true;从Spring Cloud Dalston开始,Feign的Hystrix支持默认关闭,必须设置该属性。

通过Fallback Factory检查回退原因

1)复制项目microservice-consumer-movie-feign,将ArtifactId修改为microservice-consumer-movie-feign-hystrix-fallback-factory。
2)在application.yml中添加feign.hystrix.enabled:true,从而开启Feign的Hystrix支持。
3)将UserFeignClient改为

package com.example.entity;

import com.example.feign.UserFeignClient;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.feign.FeignLoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
    private static final Logger LOGGER = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
    @Override
    public UserFeignClient create(Throwable cause) {
        return new UserFeignClient() {
            @Override
            public User findById(Long id) {
                //日志最好放在各个fallback中,而不要直接放在create方法中
                //否则在引用启动时,就会打印该日志
                FeignClientFallbackFactory.LOGGER.info("fallback; reason was:",cause);
                User user=new User();
                user.setId(-1L);
                user.setUsername("默认用户");
                return user;
            }
        };
    }
}

测试
1)启动microservice-discovery-eureka。
2)启动microservice-provider-user。
3)启动microservice-consumer-movie-feign-hystrix-fallback-factory。
4)访问http://localhost:8010/user/1能正常获得结果。
在这里插入图片描述

5)停止microservice-provider-user。
6)再次访问http://localhost:8010/user/1

在这里插入图片描述
在这里插入图片描述
注:fallbackFactory属性还有很多其他的用途,例如让不同的异常返回不同的回退结果,从而使Feign的回退更加灵活。

为Feign禁用Hystrix

前文说过,在Spring Cloud中,只要Hystrix在项目的classpath中,Feign就会使用断路器包裹Feign客户端的所有方法。这里虽然方便,但很多场景并不需要该功能。

  • 为指定Feign客户端禁用Hystrix:借助Feign的自定义配置,可轻松为指定名称的Feign客户端禁用Hystrix。
package com.example.config;

import feign.Feign;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class FeignDisableHystrixConfiguration {
    @Bean
    @Scope("proptotye")
    public Feign.Builder feignBuilder(){
        return Feign.builder();
    }
}

想要禁用Hystrix的@FeignClient,引用该配置类即可。

@FeignClient(name = "microservice-provider-user",configuration = FeignDisableHystrixConfiguration.class)
public interface UserFeignClient {
	//....
}
  • 全局禁用Hystrix:也可为Feign全局禁用Hystrix。只需在application.yml中配置
    feign.hystrix.enable = false即可。

Hystrix的监控

除实现容错外,Hystrix还提供了近乎实时的监控。HystrixCommand和HystrixObservableCommand在执行时,会生成执行结果和运行指标,比如每秒执行的请求数、成功数等,这些监控数据对分析应用系统的状态很有用。
使用Hystrix的模块hystrix-metrics-event-stream,就可将这些监控的指标信息以text/event-stream的格式暴露给外部系统。spring-cloud-starter-netflix-hystrix已包含该模块,在此基础上,只需为项目添加spring-boot-starter-actuator,就可使用/hystrix.stream端点获得Hystrix的健康信息了。
如上所述,前文的项目microservice-consumer-movie-ribbon-hystrix已具备监控Hystrix的能力。
在这里插入图片描述

测试
1)启动项目microservice-discovery-eureka。
2)启动项目microservice-provider-user。
3)启动项目microservice-consumer-movie-ribbon-hystrix。
4)访问http://localhost:8010/hystrix.stream,可看到浏览器一直处于请求的状态,页面空白。这是因为此时项目中注解了@HystrixCommand的方法还没有被执行,因此也没有任何的监控数据。
在这里插入图片描述

5)访问http://localhost:8010/user/1后,再次访问http://localhost:8010/hystrix.stream
在这里插入图片描述
这是因为系统会不断地刷新以获得实时地监控数据。Hystrix地监控指标非常全面,例如HystrixCommand地名称、group名称、断路器状态、错误率、错误数等。

Feign项目地Hystrix监控

启动前文的microservice-consumer-movie-feign-hystrix-fallback项目,并使用类似的方法测试,访问http://localhost:8010/hystrix.stream,发现返回的是404。
查看项目的依赖树会发现,项目没有hystrix-metrics-event-stream的依赖都没有。
在这里插入图片描述
解决方案
1)复制项目microservice-consumer-movie-feign-hystrix-fallback,将ArtifactId修改为microservice-consumer-movie-feign-hystrix-fallback-stream。
2)为项目添加spring-cloud-starter-netflix-hystrix的依赖。

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

3)在启动类上添加@EnableCircuitBreaker,这样就可使用/hystrix.stream端点监控Hystrix了。
在这里插入图片描述

使用Hystrix Dashboard可视化监控数据

可使用Hystrix Dashboard,让监控数据图形化、可视化。
1)创建一个Maven项目,ArtifactId是microservice-hystrix-dashboard,并为项目添加以下依赖。

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-dashboard</artifactId>
        </dependency>

2)编写启动类,在启动类上添加@EnableHystrixDashboard。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
    public static void main(String[] args){
        SpringApplication.run(HystrixDashboardApplication.class,args);
    }
}

这样,一个简单的Hystrx Dashboard就完成了。
测试
1)启动microservice-hystrix-dashboard
2)访问http://localhost:8030/hystrix,可看到主页
在这里插入图片描述
3)在上一节测试的基础上,在URL一栏输入http://localhost:8010/hystrix.stream,随意设置一个Title,单击Monitor Stream按钮后。
在这里插入图片描述

使用Turbine聚合监控数据

前文中使用/hystrix.stream端点监控单个微服务实例。然而,使用微服务架构的应用系统一般会包含若干个微服务,每个微服务通常都会部署多个实例。如果每次只能查看单个实例的监控数据,就必须在Hystrix Dashboard上切换想要监控的地址,这显然很不方便。

Turbine简介

Turbine是一个聚合Hystrix监控数据的工具,它可将所有相关/hystrix.stream端点的数据聚合到一个组合的/turbine.stream中,从而让集群的监控更加方便。

使用Turbine监控多个微服务

1)为了让Turbine监控2个以上的微服务,先将项目microservice-consumer-movie-feign-hystrix-fallback的application.yml改为

server:
  port: 8020
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
spring:
  application:
    name: microservice-consumer-movie-feign-hystrix-fallback-stream
feign:
  hystrix:
    enabled: true

2)创建一个Maven项目,ArtifactId是microservice-hystrix-turbine,并为项目添加以下依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
        </dependency>

3)在启动类上添加@EnableTurbine注解

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

@SpringBootApplication
@EnableTurbine
public class TurbineApplication {
    public static void main(String[] args){
        SpringApplication.run(TurbineApplication.class,args);
    }
}

4)编写配置文件application.yml

server:
  port: 8031
spring:
  application:
    name: microservice-hystrix-turbine
eureka:
  client:
    service-url: 
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
turbine:
  app-config: microservice-consumer-movie,microservice-consumer-movie-feign-hystrix-fallback-stream
  cluster-name-expression: "'default'"

使用以上配置,Turbine会在Eureka会在Eureka Server中找到microservice-consumer-movie和microservice-consumer-movie-feign-hystrix-fallback这两个微服务,并聚合两个微服务的监控数据。
测试
1)启动项目microservice-discovery-eureka。
2)启动项目microservice-provider-user。
3)启动项目microservice-consumer-movie-ribbon-hystrix。
4)启动项目microservice-consumer-movie-feign-hystrix-fallback。
5)启动项目microservice-hystrix-dashboard
6)启动项目microservice-hystrix-turbine
7)访问http://localhost:8010/user/1,让microservice-consumer-movie-ribbon-hystrix微服务产生监控数据。
8)访问http://localhost:8020/user/1,让microservice-consumer-movie-feign-hystrix-fallback微服务产生监控数据。
9)打开http://localshot:8030/hystrix.stream,在URL一栏填入http://localhost:8031/turbine.stream,随意指定一个Title并单击Monitor Stream按钮后。
在这里插入图片描述

使用消息中间件收集数据

一些场景下,前文的方式无法正常工作(例如微服务与Turbine网络不通),此时,可借助消息中间件实现数据收集。各个微服务将Hystrix Command的监控数据发送至消息中间件,Turbine消息中间件中的数据。
开启之前安装的RabbitMQ
1)复制项目microservice-consumer-movie-ribbon-hystrix,将ArtifactId修改为microservice-consumer-movie-ribbon-hystrix-turbine-mq。
2)添加以下依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

3)在配置文件application.yml中添加如下内容,连接RabbitMQ

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
改造Turbine

改造完微服务后,接下来改造Turbine
1)复制项目microservice-hystrix-turbine,将ArtifactId修改为microservice-hystrix-turbine-mq。
2)在pom.xml中,添加如下内容

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine-stream</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

删除

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
        </dependency>

3)修改启动类,将注解@EnableTurbine修改为@EnableTurbineStream。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.turbine.stream.EnableTurbineStream;

@SpringBootApplication
@EnableTurbineStream
public class TurbineMqApplication {
    public static void main(String[] args){
        SpringApplication.run(TurbineMqApplication.class,args);
    }
}

4)修改配置文件application.yml,添加如下内容

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

同时,删除

turbine:
  app-config: microservice-consumer-movie,microservice-consumer-movie-feign-hystrix-fallback-stream
  cluster-name-expression: "'default'"

测试
1)启动项目microservice-discovery-eureka。
2)启动项目microservice-provider-user。
3)启动项目microservice-consumer-movie-ribbon-hystrix-turbine-mq。
6)启动项目microservice-hystrix-turbine-mq。
5)访问http://localhost:8010/user/1,可正常获得结果。
6)访问http://localhost:8031/,会发现Turbine能够持续不断地显示监控数据。
在这里插入图片描述
注:务必注意,依赖spring-cloud-starter-netflix-turbine不能与spring-cloud-starter-netflix-turbine-stream共存,否则应用将无法启动!不仅如此,这两个依赖所使用的Turbine版本也不相同——spring-cloud-starter-netflix-turbine使用的Turbine版本是1.0.0,而spring-cloud-starter-netflix-turbine-stream使用的版本是2.0.0-DP.2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较复杂的需求,需要涉及到多个方面的技术。下面我尝试给你提供一个基本的架构思路和代码实现示例,供你参考。 1. 系统功能服务设计 根据需求,我们需要实现两个系统功能服务,可以分别命名为ServiceA和ServiceB。为了方便演示,这里我们简化服务功能,ServiceA提供一个加法运算服务,ServiceB提供一个字符串反转服务。 ServiceA代码示例: ``` @RestController public class ServiceAController { @GetMapping("/add") public int add(@RequestParam("a") int a, @RequestParam("b") int b) { return a + b; } } ``` ServiceB代码示例: ``` @RestController public class ServiceBController { @GetMapping("/reverse") public String reverse(@RequestParam("str") String str) { return new StringBuilder(str).reverse().toString(); } } ``` 2. Eureka服务发现 为了实现服务之间的通信,我们可以使用Eureka技术实现服务发现和注册。Eureka是一个基于REST的服务,用于定位服务,以实现间层服务器的负载平衡和故障转移。下面是Eureka服务端和客户端的代码示例。 Eureka服务端代码示例: ``` @SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } ``` Eureka客户端代码示例: ``` @SpringBootApplication @EnableDiscoveryClient public class ServiceAApplication { public static void main(String[] args) { SpringApplication.run(ServiceAApplication.class, args); } } ``` ``` @SpringBootApplication @EnableDiscoveryClient public class ServiceBApplication { public static void main(String[] args) { SpringApplication.run(ServiceBApplication.class, args); } } ``` 3. Hystrix服务容错保护服务降级 为了保证系统的健壮性,我们可以使用Hystrix技术实现服务容错保护服务降级。Hystrix一个用于处理分布式系统的延迟和容错的库,它提供了保护和控制分布式系统间组件的交互。 下面是ServiceA服务Hystrix代码示例: ``` @RestController public class ServiceAController { @Autowired private ServiceBClient serviceBClient; @GetMapping("/add") @HystrixCommand(fallbackMethod = "addFallback") public int add(@RequestParam("a") int a, @RequestParam("b") int b) { return serviceBClient.reverse(a, b); } public int addFallback(int a, int b) { return -1; } } ``` 下面是ServiceB服务Hystrix代码示例: ``` @RestController public class ServiceBController { @GetMapping("/reverse") @HystrixCommand(fallbackMethod = "reverseFallback") public String reverse(@RequestParam("str") String str) { if (str == null || str.isEmpty()) { throw new IllegalArgumentException("String cannot be empty"); } return new StringBuilder(str).reverse().toString(); } public String reverseFallback(String str) { return ""; } } ``` 4. 网关路由功能 为了实现网关路由功能,我们可以使用Spring Cloud Gateway技术,它是Spring Cloud生态系统的网关解决方案。它基于Spring Framework 5,Project Reactor和Spring Boot 2.0,可以用作Zuul的替代方案。 下面是网关路由配置文件示例: ``` spring: cloud: gateway: routes: - id: serviceA uri: lb://service-a predicates: - Path=/serviceA/** - id: serviceB uri: lb://service-b predicates: - Path=/serviceB/** ``` 5. 接口自动生成在线接口文档 为了方便对外提供服务接口,我们可以使用Swagger技术自动生成在线接口文档。Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化Restful风格的Web服务。 下面是Swagger配置示例: ``` @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("com.example")) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Example API") .description("Example API reference for developers") .version("1.0") .build(); } } ``` 以上是一个基本的后端微服务架构代码示例,实现了多个功能模块,包括服务发现、服务容错保护服务降级、网关路由和在线接口文档。由于每个公司的技术栈和业务需求不同,实际的架构实现可能会有所不同,需要根据具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值