本示例主要介绍 Spring Cloud 系列中的 Eureka,如何使用Hystrix熔断器容错保护我们的应用程序。

在微服务架构中,系统被拆分成很多个服务单元,各个服务单元的应用通过 HTTP 相互调用、依赖,在某个服务由于网络或其他原因自身出现故障、延迟时,调用方也会出现延迟。若调用方请求不断增加,可能会形成任务积压,最终导致调用方服务瘫痪,服务不可用现象逐渐放大。

解决方案

Spring Cloud Hystrix 是一个专用于服务熔断处理的开源项目,实现了一系列服务保护措施,当依赖的服务方出现故障不可用时,hystrix实现服务降级、服务熔断等功能,对延迟和故障提供强大的容错能力,从而防止故障进一步扩大。

Hystrix 主要作用介绍

  • 保护和控制底层服务的高延迟和失效对上层服务的影响。
  • 避免复杂分布式中服务失效的雪崩效应。在大型的分布式系统中,存在各种复杂的依赖关系。如果某个服务失效,很可能会对其他服务造成影响,形成连锁反应。
  • 快速失效和迅速恢复。以Spring为例,一般在实现controller的时候,都会以同步的逻辑调用依赖的服务。如果服务失效,而且没有客户端失效机制,就会导致请求长时间的阻塞。如果不能快速的发现失效,而就很难通过高可用机制或者负载均衡实现迅速的恢复。
  • 实现服务降级。这一点是从用户体验来考虑的,一个预定义默认返回会比请求卡死或者500好很多。
  • 实现了服务监控、报警和运维控制。Hystrix Dashboard和Turbine可以配合Hystrix完成这些功能。

Hystrix 主要特性:

  • 服务熔断

    Hystrix 会记录各个服务的请求信息,通过 成功、失败、拒绝、超时 等统计信息判断是否打开断路器,将某个服务的请求进行熔断。一段时间后切换到半开路状态,如果后面的请求正常则关闭断路器,否则继续打开断路器。

  • 服务降级

    服务降级是请求失败时的后备方法,故障时执行降级逻辑。

  • 线程隔离

    Hystrix 通过线程池实现资源的隔离,确保对某一服务的调用在出现故障时不会对其他服务造成影响。

代码实现

创建三个项目来完成示例,分别为:服务注册中心hystrix-eureka-server,服务提供者hystrix-service-provider,服务消费者hystrix-service-consumer

1.创建hystrix-eureka-server服务注册中心

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.easy</groupId>
<artifactId>hystrix-eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>hystrix-eureka-server</name>
<description>Demo project for Spring Boot</description> <parent>
<artifactId>cloud-hystrix</artifactId>
<groupId>com.easy</groupId>
<version>1.0.0</version>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

application.yml配置文件

server:
port: 8761 spring:
application:
name: eureka-server eureka:
instance:
hostname: localhost # eureka 实例名称
client:
register-with-eureka: false # 不向注册中心注册自己
fetch-registry: false # 是否检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 注册中心访问地址

HystrixEurekaServerApplication.java启动类

package com.easy.eurekaServer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer
@SpringBootApplication
public class HystrixEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixEurekaServerApplication.class, args);
}
}

2.创建hystrix-service-provider服务提供者

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.easy</groupId>
<artifactId>hystrix-service-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>hystrix-service-provider</name>
<description>Demo project for Spring Boot</description> <parent>
<artifactId>cloud-hystrix</artifactId>
<groupId>com.easy</groupId>
<version>1.0.0</version>
</parent> <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>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

application.yml配置文件

spring:
application:
name: hystrix-service-provider eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
# 实例一
server:
port: 8081

HelloController.java提供一个hello接口

package com.easy.serviceProvider.web;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; @RestController
public class HelloController { @GetMapping("hello")
public String hello(@RequestParam String p1, @RequestParam String p2) throws Exception {
// 用来测试服务超时的情况
// int sleepTime = new Random().nextInt(2000);
// System.out.println("hello sleep " + sleepTime);
// Thread.sleep(sleepTime);
return "hello, " + p1 + ", " + p2;
}
}

最后贴上启动类HystrixServiceProviderApplication.java

package com.easy.serviceProvider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @EnableDiscoveryClient
@SpringBootApplication
public class HystrixServiceProviderApplication { public static void main(String[] args) {
SpringApplication.run(HystrixServiceProviderApplication.class, args);
}
}

3.创建hystrix-service-consumer服务消费者

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.easy</groupId>
<artifactId>hystrix-service-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging> <name>hystrix-service-consumer</name>
<description>Demo project for Spring Boot</description> <parent>
<artifactId>cloud-hystrix</artifactId>
<groupId>com.easy</groupId>
<version>1.0.0</version>
</parent> <dependencies>
<!-- eureka 客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!-- ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

application.yml配置文件

spring:
application:
name: hystrix-eureka-server
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/ hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 1000 # 默认超时时间

相关代码

异常处理类NotFallbackException.java

package com.easy.serviceConsumer.exception;

public class NotFallbackException extends Exception {
}

服务层HelloService.java

package com.easy.serviceConsumer.service;

import com.easy.serviceConsumer.exception.NotFallbackException;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate; @Service
public class HelloService { @Autowired
RestTemplate restTemplate; private static final String HELLO_SERVICE = "http://hystrix-service-provider/"; @HystrixCommand(fallbackMethod = "helloFallback", ignoreExceptions = {NotFallbackException.class}
, groupKey = "hello", commandKey = "str", threadPoolKey = "helloStr")
public String hello(String p1, String p2) {
return restTemplate.getForObject(HELLO_SERVICE + "hello?p1=" + p1 + "&p2=" + p2, String.class);
} private String helloFallback(String p1, String p2, Throwable e) {
System.out.println("class: " + e.getClass());
return "error, " + p1 + ", " + p2;
}
}

控制器ConsumerController.java

package com.easy.serviceConsumer.web;

import com.easy.serviceConsumer.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; @RestController
public class ConsumerController { @Autowired
HelloService helloService; @GetMapping("hello")
public String hello(@RequestParam String p1, @RequestParam String p2) {
System.out.println("hello");
return helloService.hello(p1, p2);
}
}

4.启动类HystrixServiceConsumerApplication.java

package com.easy.serviceConsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate; @SpringCloudApplication
public class HystrixServiceConsumerApplication { @Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
} public static void main(String[] args) {
SpringApplication.run(HystrixServiceConsumerApplication.class, args);
}
}

使用示例

分别运行3个服务,HystrixEurekaServerApplication.java(服务注册中心),HystrixServiceProviderApplication.java(服务提供者),HystrixServiceConsumerApplication.java(服务消费者)

资料

分布式系统的延时和故障容错之Spring Cloud Hystrix的更多相关文章

  1. SpringCloud---服务容错保护---Spring Cloud Hystrix

    1.概述 1.1 在分布式架构中,存在着许多的服务单元,若一个单元出现故障,很容易因依赖关系引发故障的蔓延,最终导致整个系统的瘫痪: 为了解决这样的问题,产生了断路器等服务保护机制: 1.2 分布式架 ...

  2. 笔记:Spring Cloud Hystrix 服务容错保护

    由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加 ...

  3. 第五章 服务容错保护:Spring Cloud Hystrix

    在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能 ...

  4. 第五章 服务容错保护: Spring Cloud Hystrix

    在微服务架构中, 存在着那么多的服务单元, 若一个单元出现故障, 就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定.为了解决这样的问题, 产生了断路器等一系 ...

  5. Spring Cloud Hystrix 服务容错保护

    目录 一.Hystrix 是什么 二.Hystrix断路器搭建 三.断路器优化 一.Hystrix 是什么 ​ 在微服务架构中,我们将系统拆分成了若干弱小的单元,单元与单元之间通过HTTP或者TCP等 ...

  6. Spring Cloud Hystrix 服务容错保护 5.1

    Spring Cloud Hystrix介绍 在微服务架构中,通常会存在多个服务层调用的情况,如果基础服务出现故障可能会发生级联传递,导致整个服务链上的服务不可用为了解决服务级联失败这种问题,在分布式 ...

  7. 容错保护机制:Spring Cloud Hystrix

    最近在学习Spring Cloud的知识,现将容错保护机制Spring Cloud Hystrix 的相关知识笔记整理如下.[采用 oneNote格式排版]

  8. Spring Cloud 微服务笔记(六)Spring Cloud Hystrix

    Spring Cloud Hystrix Hystrix是一个延迟和容错库,旨在隔离远程系统.服务和第三方库,阻止链接故障,在复杂的分布式系统中实现恢复能力. 一.快速入门 1)依赖: <dep ...

  9. Spring Cloud Hystrix理解与实践(一):搭建简单监控集群

    前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring ...

随机推荐

  1. Joyful HDU - 5245 概率问题

    Sakura has a very magical tool to paint walls. One day, kAc asked Sakura to paint a wall that looks ...

  2. zoj 5823 Soldier Game 2018 青岛 I

    题目传送门 题意:现在有n个人,现在可以把这n个人分成若干组,只有连续的人才能被分为一组,并且一个组内最多2个人,现在问你 所有组内的最大值-最小值 这个差值最小是多少. 题解: 将每个人的情况3种情 ...

  3. 基于SpringBoot从零构建博客网站 - 开发文章详情页面

    文章详情页面是博客系统中最为重要的页面,登录用户与游客都可以浏览文章详情页面,只不过只有登录用户才能进行其它的一些操作,比如评论.点赞和收藏等等. 本次的开发任务只是将文章详情页面展示出来,至于一些收 ...

  4. 带你深入了解NPM——NPM初学者指南

    前段时间,我们邀请了我们“城内”(葡萄城)资深开发工程师刘涛为大家分享了一次干货满满的关于Electron线上公开课,在课程过程中有不少同学对于NPM的概念和用法有一些疑问,所以这次我们希望通过这篇文 ...

  5. Linux系统下安装zookeeper教程

    环境: 1.VMware® Workstation 12 Pro 2.CentOS7 3.zookeeper-3.4.6 安装步骤 1.下载zookeeper 本文使用的zookeeper下载地址如下 ...

  6. 分库分表之后,id 主键如何处理?

    其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定不对啊,需要一个全局唯一的 id 来支持.所以这都是你实际生产环境中必须考虑的 ...

  7. 致初学者(三): HDU 2033~ 2043题解

    下面继续给出HDU 2033~2043的AC程序,供大家参考.2033~2043这10道题就被归结为“ACM程序设计期末考试(2006/06/07) ”和“2005实验班短学期考试 ”. HDU 20 ...

  8. Docker下kafka学习三部曲之二:本地环境搭建

    在上一章< Docker下kafka学习,三部曲之一:极速体验kafka>中我们快速体验了kafka的消息分发和订阅功能,但是对环境搭建的印象仅仅是执行了几个命令和脚本,本章我们通过实战来 ...

  9. STL迭代器

    大部分ACM中使用的都是C/C++语言,但是说到C语言和C++语言的区别,却不知道. C++语言用于竞赛真的是非常方便的,里面有很多函数还有STL这个好东西,比C语言方便,比其他语言好理解. 在C语言 ...

  10. IO流——File类(文件流类)

    java语言的输入输出操作是借助于输入输出包java.io来实现的,按传输方向分为输入流与输出流,从外设传递到应用程序的流为输入流,将数据从应用程序输入到外设的流为输出流. File类的构造方法: 1 ...