服务降级

服务压力剧增的时候,根据当前的业务情况及流量对一些服务和页面有策略的降级,以此缓解服务器的压力,以保证核心任务的进行。同时保证部分甚至大分客户能得到正确的响应。也就是当前的请求处理不了或者出错了,给一个默认的返回。例如:双11降级产品评价等非核心功能,保证支持和订单的核心任务进行。

服务熔断

就是防止服务雪崩现象出现,是服务降级的一种特殊情况。

一、Hystrix的服务使用前的问题

1、ProductController 中方法异常和超时

在商品服务 ProductController 中的方法中增加异常和超时,ProductController 中方法修改如下:

package com.hwadee.springcloud.controller;
import com.hwadee.springcloud.entity.Product;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
@RestController
@RequestMapping("/product")
public class ProductController {
    //方便后面讲负载均衡,查看ip,此处获取配置中的端口号和ip
    @Value("${server.port}")
    private String port;
    @Value("${spring.cloud.client.ip-address}")
    private String ip;
    @RequestMapping("/buy/{id}")
    public Product findById(@PathVariable Long id) {
        Product product = new Product();
        product.setId(id);
        // 后面需要测试负载均衡,所以返回 ip 地址及端口号
        product.setName("当前访问商品服务地址:"   ip   ":"   port "  " "查询商品订单,订单号:" id);
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        //测试超时熔断
        try {
            Thread.sleep(5000);
            //测试并发熔断
            //Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return product;
    }
    @RequestMapping(value = "/delete/{id}")
    public Product deleteOrderById(@PathVariable Long id){
        Product product = new Product();
        product.setId(id);
        // 后面需要测试负载均衡,所以返回 ip 地址及端口号
        product.setName("当前访问商品服务地址:"   ip   ":"   port "  " "从购物车删除订单,订单号:" id);
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        //测试异常熔断
        System.out.println(10/0);
        return product;
    }
}

2、访问查看效果

访问http://localhost:9000/order/buy/1

访问http://localhost:9000/order/delete/1

订单服务中OrderController 中 调用商品服务 ProductController 中方法时,ProductController 中方法出现异常和超时,访问浏览器的异常结果和订单服务中的内部异常如下:

3、问题分析

在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,进一步甚至出现故障的蔓延最终导致整个系统的瘫痪。如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定,如下图。

二、 商品服务 Hystrix的 局部降级

1、降级配置

注解 @HistrixCommand

在商品服务 ProductController 中的 findById( )和deleteOrderById( ) 方法上增加降级配置的注解 @HistrixCommand

—旦调用服务方法失败并抛出了超时或错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。

在@HistrixCommand 指定超时或异常要回调的方法,同时可以指定配置参数,例如使用@HistrixCommand 中的属性commandProperties 指定默认超时时间,如:

fallbackMethod:指定回调方法是findByIdTimeout
commandProperties: 指定@HystrixProperty​​​ ​的默认值是默认超时时间是3s

@HystrixCommand(fallbackMethod = "findByIdTimeout", commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})

2、回调(兜底降级)方法

在商品服务ProductController 中增加回调方法findByIdTimeout( ) 和deleteOrderByIdException( ),当访问ProductController 中的 findById( )和deleteOrderById( ) 发生超时 或 异常时,会调用回调方法。

3、具体代码

降级配置 和回调(兜底降级)方法的具体代码如下:

import com.hwadee.springcloud.entity.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
@RestController
@RequestMapping("/product")
public class ProductController {
    //方便后面讲负载均衡,查看ip,此处获取配置中的端口号和ip
    @Value("${server.port}")
    private String port;
    @Value("${spring.cloud.client.ip-address}")
    private String ip;
    @RequestMapping("/buy/{id}")
    @HystrixCommand(fallbackMethod = "findByIdTimeout", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public Product findById(@PathVariable Long id) {
        Product product = new Product();
        product.setId(id);
        // 后面需要测试负载均衡,所以返回 ip 地址及端口号
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "查询商品订单,订单号:"   id);
        product.setPrice(new BigDecimal(50000.0));
        System.out.println(product);
        //测试超时熔断
        try {
            Thread.sleep(5000);
            //测试并发熔断
            //Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return product;
    }
    @RequestMapping(value = "/delete/{id}")
    @HystrixCommand(fallbackMethod = "deleteOrderByIdException")
    public Product deleteOrderById(@PathVariable Long id) {
        Product product = new Product();
        product.setId(id);
        // 后面需要测试负载均衡,所以返回 ip 地址及端口号
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "从购物车删除订单,订单号:"   id);
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        //测试异常熔断
        System.out.println(10 / 0);
        return product;
    }
    public Product findByIdTimeout(Long id) {
        Product product = new Product();
        product.setId(id);
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "访问 超时 进行降级服务");
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        return product;
    }
    public Product deleteOrderByIdException(Long id) {
        Product product = new Product();
        product.setId(id);
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "访问 异常 进行降级服务");
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        return product;
    }
}

4、主启动类激活Hstrix

在商品服务的主启动类 ProductServerApplication 中使用注解@EnableCircuitBreaker 进行激活Hystrix,代码如下

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient// 启动 eureka 客户端
@EnableCircuitBreaker // 主启动类激活 Hystrix
public class ProductServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductServerApplication.class, args);
    }
}

5、进行测试

将商品服务中ProductController 和 ProductServerApplication复制到 其他所有 商品服务中,进行更新代码。

分别访问:http://localhost:9001/product/buy/1 和 http://localhost:9001/product/delete/1 查看超时和异常服务降级。看浏览器和内部结果。

三、 订单服务 Hystrix的 局部降级

1、降级配置

注解 @HistrixCommand

在订单服务 OrderController 中的方法上增加降级配置的注解 @HistrixCommand

2、回调(兜底降级)方法

在订单服务 OrderController 定义 回调方法 buyTimeout( Long id) 、deleteOrderException( Long id),并设置超时服务,超时服务要比将商品服务ProductController 中的 findById( ) 超时时间短。例如:ProductController 中的 findById( ) 超时时间是 3s ,则订单服务 OrderController 定义 回调方法 buyTimeout( ) 设定的超时时间应是 <3s 。

3、具体代码

降级配置 和回调(兜底降级)方法的具体代码如下:

import com.hwadee.springcloud.entity.Product;
import com.hwadee.springcloud.service.IOrderFeignService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    IOrderFeignService orderFeignService;
    @RequestMapping("/buy/{id}")
    @HystrixCommand(fallbackMethod = "buyTimeout", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
    })
    public Product buy(@PathVariable Long id) {
        System.out.println("进入OrderController的buy方法, orderFeignService 准备调用远端接口 findById");
        Product product = orderFeignService.findOrderById(id);
        return product;
    }
    @RequestMapping(value = "/delete/{id}")
    @HystrixCommand(fallbackMethod = "deleteOrderException")
    public Product deleteOrderById(@PathVariable Long id) {
        System.out.println("进入OrderController的deleteOrderById方法, orderFeignService 准备调用远端接口deleteOrderById");
        Product product = orderFeignService.deleteOrderById(id);
        int i =10/0;
        return product;
    }
    public Product buyTimeout( Long id) {
        Product product = new Product();
        product.setId(id);
        product.setName("当前订单服务访问/order/buy/1 超时:" id);
        return product;
    }
    public Product deleteOrderException( Long id) {
        Product product = orderFeignService.deleteOrderById(id);
        product.setName("当前订单服务访问/order/delete/1 10/0异常:" id);
        return product;
    }
}

4、将商品服务中的超时时间为正常

将商品服务ProductController 中的 findById( ) 超时时间为正常,即程序超时时间是2s,熔断等待时间是3s,并且要比 订单服务 OrderController 定义 回调方法 buyTimeout( ) 中的熔断时间大,代码如下:

@HystrixCommand(fallbackMethod = "findByIdTimeout", commandProperties = {

// 正常超时时间是 3s 比OrderController 中定义的超时时间长。

@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") }) public Product findById(@PathVariable Long id) { 。。。。。

// 超时时间 2s

Thread.sleep(2000); 。。。。。

return product;

}

完整代码如下:

import com.hwadee.springcloud.entity.Product;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
@RestController
@RequestMapping("/product")
public class ProductController {
    //方便后面讲负载均衡,查看ip,此处获取配置中的端口号和ip
    @Value("${server.port}")
    private String port;
    @Value("${spring.cloud.client.ip-address}")
    private String ip;
    @RequestMapping("/buy/{id}")
    @HystrixCommand(fallbackMethod = "findByIdTimeout", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public Product findById(@PathVariable Long id) {
        Product product = new Product();
        product.setId(id);
        // 后面需要测试负载均衡,所以返回 ip 地址及端口号
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "查询商品订单,订单号:"   id);
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        //测试超时熔断
        try {
            Thread.sleep(5000);
            //测试并发熔断
            //Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return product;
    }
    @RequestMapping(value = "/delete/{id}")
    @HystrixCommand(fallbackMethod = "deleteOrderByIdException")
    public Product deleteOrderById(@PathVariable Long id) {
        Product product = new Product();
        product.setId(id);
        // 后面需要测试负载均衡,所以返回 ip 地址及端口号
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "从购物车删除订单,订单号:"   id);
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        //测试异常熔断
        System.out.println(10 / 0);
        return product;
    }
    public Product findByIdTimeout(Long id) {
        Product product = new Product();
        product.setId(id);
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "访问 超时 进行降级服务");
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        return product;
    }
    public Product deleteOrderByIdException(Long id) {
        Product product = new Product();
        product.setId(id);
        product.setName("当前访问商品服务地址:"   ip   ":"   port   "  "   "访问 异常 进行降级服务");
        product.setPrice(new BigDecimal(10000.0));
        System.out.println(product);
        return product;
    }
}

5、主启动类激活Hstrix

在订单服务的主启动类 OrderServerApplication 中使用注解@EnableCircuitBreaker 或 注解@EnableHystrix进行激活Hystrix,注意:@EnableHystrix包括了注解@EnableCircuitBreaker ,代码如下

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient// 启动 eureka 客户端
@EnableFeignClients  // 启动 feign
@EnableCircuitBreaker // 或 @EnableHystrix  启动 Hystrix
public class OrderServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServerApplication.class, args);
    }
}

6、进行测试

分别访问:http://localhost:9000/order/buy/1 和 http://localhost:9000/order/delete/1 查看超时和异常服务降级。

到此这篇关于SpringCloud hystrix断路器与服务降级全面介绍的文章就介绍到这了,更多相关SpringCloud hystrix断路器内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

SpringCloud hystrix断路器与局部降级全面介绍的更多相关文章

  1. SpringCloud超详细讲解微服务网关Zuul基础

    这篇文章主要介绍了SpringCloud Zuul微服务网关,负载均衡,熔断和限流,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. SpringCloud gateway+zookeeper实现网关路由的详细搭建

    这篇文章主要介绍了SpringCloud gateway+zookeeper实现网关路由,本文通过图文实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. SpringCloud OpenFeign 服务调用传递 token的场景分析

    这篇文章主要介绍了SpringCloud OpenFeign 服务调用传递 token的场景分析,本篇文章简单介绍 OpenFeign 调用传递 header ,以及多线程环境下可能会出现的问题,其中涉及到 ThreadLocal 的相关知识,需要的朋友可以参考下

  4. Springcloud Stream消息驱动工具使用介绍

    SpringCloud Stream由一个中间件中立的核组成,应用通过SpringCloud Stream插入的input(相当于消费者consumer,它是从队列中接收消息的)和output(相当于生产者producer,它是发送消息到队列中的)通道与外界交流

  5. SpringCloud中Gateway的使用教程详解

    SpringCloud Gateway是Spring体系内的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。本文就来为大家详细讲讲Gateway的使用教程,需要的可以参考一下

  6. SpringCloud 客户端Ribbon负载均衡的实现方法

    Ribbon 是 Netflix 提供的一个基于 Http 和 TCP 的客户端负载均衡工具,且已集成在 Eureka 依赖中,这篇文章主要介绍了SpringCloud 客户端Ribbon负载均衡的实现方法,需要的朋友可以参考下

  7. SpringCloud服务网关Gateway的使用教程详解

    SpringCloud Gateway是Spring体系内的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。本文就来为大家详细讲讲Gateway的使用教程,需要的可以参考一下

  8. SpringCloud 分布式微服务架构操作步骤

    SpringCloud是一种微服务的框架,利用它我们可以去做分布式服务开发,这篇文章主要介绍了SpringCloud 分布式微服务架构,需要的朋友可以参考下

  9. SpringCloud迈向云原生的步骤

    这篇文章主要介绍了SpringCloud怎么迈向云原生,通过本文我们来梳理一下Spring Cloud的前世今生,以及未来云原生发展的趋势,可以给这些RPC框架的演进带来一些启发,感兴趣的朋友跟随小编一起看看吧

  10. Spring Cloud Alibaba微服务组件Sentinel实现熔断限流

    这篇文章主要为大家介绍了Spring Cloud Alibaba微服务组件Sentinel实现熔断限流过程示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部