時念
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
    • JavaScript 基础
  • 后端笔记

    • Java
    • Spring
    • 算法
    • 高可用
    • 高并发
  • 工作问题

    • 问题记录
  • 各类工具使用
  • GitHub技巧
  • 博客搭建
  • 面试题库

    • 零碎
    • 面试常见题目汇总
  • 面试心得

    • 面试集锦
    • 杂言碎语
  • 摘抄收录

    • ☆ 励志鸡汤
    • ❀ 人间烟火
    • ☣ 万物沦丧
    • ✌ 关掉烦恼
    • ✲ 小酒馆
  • 读书笔记

    • 《小狗钱钱》
    • 《穷爸爸富爸爸》
    • 《聪明人使用方格笔记本》
  • 学习
  • 心情杂货
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub

時念

一个有梦想的后端小菜鸡(✪ω✪)
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
    • JavaScript 基础
  • 后端笔记

    • Java
    • Spring
    • 算法
    • 高可用
    • 高并发
  • 工作问题

    • 问题记录
  • 各类工具使用
  • GitHub技巧
  • 博客搭建
  • 面试题库

    • 零碎
    • 面试常见题目汇总
  • 面试心得

    • 面试集锦
    • 杂言碎语
  • 摘抄收录

    • ☆ 励志鸡汤
    • ❀ 人间烟火
    • ☣ 万物沦丧
    • ✌ 关掉烦恼
    • ✲ 小酒馆
  • 读书笔记

    • 《小狗钱钱》
    • 《穷爸爸富爸爸》
    • 《聪明人使用方格笔记本》
  • 学习
  • 心情杂货
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub
  • java

  • spring

  • 问题记录

  • 算法

  • 高可用

    • index
    • Hystrix介绍
    • 电商网站详情页系统架构
    • Hystrix线程池技术实现资源隔离
    • Hystrix信号量机制实现资源隔离
    • Hystrix隔离策略细粒度控制
    • 深入Hystrix执行时内部原理
    • 基于requestcache请求缓存技术优化批量商品数据查询接口
    • 基于本地缓存的fallback降级机制
    • 深入Hystrix断路器执行原理
    • 深入Hystrix线程池隔离与接口限流
    • 基于timeout机制为服务接口调用超时提供安全保护
      • 基于 timeout 机制为服务接口调用超时提供安全保护
        • TimeoutMilliseconds
        • TimeoutEnabled
      • 实例 Demo
    • sentinel-vs-hystrix
  • 后端
  • 高可用
時念
2024-03-08

基于 timeout 机制为服务接口调用超时提供安全保护

# 基于 timeout 机制为服务接口调用超时提供安全保护

一般来说,在调用依赖服务的接口的时候,比较常见的一个问题就是超时。超时是在一个复杂的分布式系统中,导致系统不稳定,或者系统抖动。出现大量超时,线程资源会被 hang 死,从而导致吞吐量大幅度下降,甚至服务崩溃。

你去调用各种各样的依赖服务,特别是在大公司,你甚至都不认识开发一个服务的人,你都不知道那个人的技术水平怎么样,对那个人根本不了解。

Peter Steiner 说过,"On the Internet, nobody knows you're a dog ",也就是说在互联网的另外一头,你都不知道甚至坐着一条狗。

220px-Internet_dog.jpg

像特别复杂的分布式系统,特别是在大公司里,多个团队、大型协作,你可能都不知道服务是谁的,很可能说开发服务的那个哥儿们甚至是一个实习生。依赖服务的接口性能可能很不稳定,有时候 2ms,有时候 200ms,甚至 2s,都有可能。

如果你不对各种依赖服务接口的调用做超时控制,来给你的服务提供安全保护措施,那么很可能你的服务就被各种垃圾的依赖服务的性能给拖死了。大量的接口调用很慢,大量的线程被卡死。如果你做了资源的隔离,那么也就是线程池的线程被卡死,但其实我们可以做超时控制,没必要让它们全卡死。

# TimeoutMilliseconds

在 Hystrix 中,我们可以手动设置 timeout 时长,如果一个 command 运行时间超过了设定的时长,那么就被认为是 timeout,然后 Hystrix command 标识为 timeout,同时执行 fallback 降级逻辑。

TimeoutMilliseconds 默认值是 1000,也就是 1000ms。

HystrixCommandProperties.Setter()
    ..withExecutionTimeoutInMilliseconds(int)
1
2

# TimeoutEnabled

这个参数用于控制是否要打开 timeout 机制,默认值是 true。

HystrixCommandProperties.Setter()
    .withExecutionTimeoutEnabled(boolean)
1
2

# 实例 Demo

我们在 command 中,将超时时间设置为 500ms,然后在 run() 方法中,设置休眠时间 1s,这样一个请求过来,直接休眠 1s,结果就会因为超时而执行降级逻辑。

public class GetProductInfoCommand extends HystrixCommand<ProductInfo> {

    private Long productId;

    private static final HystrixCommandKey KEY = HystrixCommandKey.Factory.asKey("GetProductInfoCommand");

    public GetProductInfoCommand(Long productId) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ProductInfoService"))
                .andCommandKey(KEY)
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                        .withCoreSize(8)
                        .withMaxQueueSize(10)
                        .withQueueSizeRejectionThreshold(8))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withCircuitBreakerEnabled(true)
                        .withCircuitBreakerRequestVolumeThreshold(20)
                        .withCircuitBreakerErrorThresholdPercentage(40)
                        .withCircuitBreakerSleepWindowInMilliseconds(3000)
                        // 设置是否打开超时,默认是true
                        .withExecutionTimeoutEnabled(true)
                        // 设置超时时间,默认1000(ms)
                        .withExecutionTimeoutInMilliseconds(500)
                        .withFallbackIsolationSemaphoreMaxConcurrentRequests(30)));
        this.productId = productId;
    }

    @Override
    protected ProductInfo run() throws Exception {
        System.out.println("调用接口查询商品数据,productId=" + productId);

        // 休眠1s
        TimeUtils.sleep(1);

        String url = "http://localhost:8081/getProductInfo?productId=" + productId;
        String response = HttpClientUtils.sendGetRequest(url);
        System.out.println(response);
        return JSONObject.parseObject(response, ProductInfo.class);
    }

    @Override
    protected ProductInfo getFallback() {
        ProductInfo productInfo = new ProductInfo();
        productInfo.setName("降级商品");
        return productInfo;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

在测试类中,我们直接发起请求。

@SpringBootTest
@RunWith(SpringRunner.class)
public class TimeoutTest {

    @Test
    public void testTimeout() {
        HttpClientUtils.sendGetRequest("http://localhost:8080/getProductInfo?productId=1");
    }
}
1
2
3
4
5
6
7
8
9

结果中可以看到,打印出了降级商品相关信息。

ProductInfo(id=null, name=降级商品, price=null, pictureList=null, specification=null, service=null, color=null, size=null, shopId=null, modifiedTime=null, cityId=null, cityName=null, brandId=null, brandName=null)
{"id": 1, "name": "iphone7手机", "price": 5599, "pictureList":"a.jpg,b.jpg", "specification": "iphone7的规格", "service": "iphone7的售后服务", "color": "红色,白色,黑色", "size": "5.5", "shopId": 1, "modifiedTime": "2017-01-01 12:00:00", "cityId": 1, "brandId": 1}
1
2
编辑
上次更新: 2024/03/26, 9:03:00
深入Hystrix线程池隔离与接口限流
sentinel-vs-hystrix

← 深入Hystrix线程池隔离与接口限流 sentinel-vs-hystrix →

最近更新
01
database-shard-dynamic-expand
03-26
02
README
03-26
03
database-shard-global-id-generate
03-26
更多文章>
Theme by Vdoing | Copyright © 2019-2024 時念 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式