[Microservice Notes 09] Hystrix of microservice components implements thread pool isolation and semaphore isolation

This article mainly introduces the implementation of thread pool isolation and semaphore isolation by Hystrix of microservice components.

Table of contents

1. Thread pool isolation

1.1. Introduction to thread pool isolation

1.2. Realize thread pool isolation

(1) Introduce dependencies

(2) Write Service layer code

(3) Write Controller layer code

(4) Run the test

2. Semaphore isolation

2.1. Introduction to semaphore isolation

2.2. Realize semaphore isolation

(1) Introduce dependencies

(2) Write Service layer code

(3) Write Controller layer code

(4) Run the test


1. Thread pool isolation

1.1. Introduction to thread pool isolation

In a microservice, if all the interfaces are running in the same thread pool, if there are a large number of requests for one of the interfaces, and this interface cannot be processed, the service may run out of resources at this time , causing the entire service to crash. Therefore, in order to solve this problem, Hystrix proposed a thread pool isolation scheme, which puts different interfaces into different thread pools for management, and different thread pools do not interfere with each other, so that even if one of the thread pools fails, it will not It will affect other thread pools, which reduces the possibility of service crashes.

Although thread pool isolation solves the problem of service crash, it also brings a problem, that is, the creation and destruction of threads need to consume system resources. If thread pool isolation is used, when the request of this microservice becomes larger and larger , the corresponding threads will be created more and more, which will lead to very frequent thread switching, which will reduce a performance of the system. Thread pool isolation is suitable for scenarios with fewer isolated instances .

1.2. Realize thread pool isolation

(1) Introduce dependencies

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

(2) Write Service layer code

In the service service layer, we use the [@HystrixCommand] annotation to mark the method that needs to enable thread pool isolation.

package com.gitcode.hystrix.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 19:49
 * @Copyright (C) ZhuYouBin
 * @Description:
 */
@Service
public class HystrixThreadService {


    @HystrixCommand(
            // 命令key,默认是当前方法名称
            commandKey = "firstCommandKey",
            // 线程池分组的key
            groupKey = "queryList-thread-pool",
            // 线程池的key,可以和 groupKey 设置相同
            threadPoolKey = "queryList-thread-pool",
            // 设置 hystrix 命令的属性
            commandProperties = {
                    // 设置线程池隔离的超时时间,默认是1000ms
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
            },
            // 设置线程池的属性
            threadPoolProperties = {
                    // 核心线程大小
                    @HystrixProperty(name = "coreSize", value = "4"),
                    // 队列大小
                    @HystrixProperty(name = "maxQueueSize", value = "100"),
                    // 存活时间,默认是 1 分钟,单位是分钟
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    // 超出队列执行拒绝策略的阈值
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "100"),
            },
            // 设置快速失败时候调用的方法,可以写,也可以不写,写了就会执行快速失败,不写就阻塞等待
            fallbackMethod = "fallbackDemo"
    )
    public String queryList() {
        // TODO 这里模拟调用其他微服务
        try {
            Thread.sleep(6000);
            System.out.println("微服务调用成功:" + Thread.currentThread().getName());
        } catch (Exception e) {}
        return "success";
    }

    @HystrixCommand(
            // 命令key,默认是当前方法名称
            commandKey = "secondCommandKey",
            // 线程池分组的key
            groupKey = "getDataById-thread-pool",
            // 线程池的key,可以和 groupKey 设置相同
            threadPoolKey = "getDataById-thread-pool",
            // 设置 hystrix 命令的属性
            commandProperties = {
                    // 设置线程池隔离的超时时间,默认是1000ms
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
            },
            // 设置线程池的属性
            threadPoolProperties = {
                    // 核心线程大小
                    @HystrixProperty(name = "coreSize", value = "2"),
                    // 队列大小
                    @HystrixProperty(name = "maxQueueSize", value = "100"),
                    // 存活时间,默认是 1 分钟,单位是分钟
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    // 超出队列执行拒绝策略的阈值
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "100"),
            }
    )
    public String getDataById() {
        // TODO 这里模拟调用其他微服务
        System.out.println("微服务调用成功:" + Thread.currentThread().getName());
        return "success";
    }

    public String fallbackDemo() {
        return "接口调用失败,请稍后重试!";
    }
}

(3) Write Controller layer code

package com.gitcode.hystrix.controller;

import com.gitcode.hystrix.service.HystrixThreadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 19:47
 * @Copyright (C) ZhuYouBin
 * @Description: Hystrix 线程池隔离
 */
@RestController
@RequestMapping("/hystrix/thread")
public class HystrixThreadController {

    @Autowired
    private HystrixThreadService hystrixThreadService;

    @GetMapping("/queryList")
    public String queryList() {
        return hystrixThreadService.queryList();
    }

    @GetMapping("/getDataById")
    public String getDataById() {
        return hystrixThreadService.getDataById();
    }
}

(4) Run the test

Start the application, and the browser accesses the two interfaces.

2. Semaphore isolation

2.1. Introduction to semaphore isolation

The use of thread pool isolation may lead to too many threads and reduce the performance of the system. Therefore, in order to solve this problem, Hystrix proposes a semaphore isolation. Semaphore isolation adopts the idea of ​​synchronous blocking and waiting. It sets a semaphore, which is used to indicate the maximum number of requests that can be accessed at the same time. When the number of requests arriving in the system exceeds this semaphore, the excess requests will be is in a blocked state, or directly adopts the fast fail mechanism and returns an error message.

Semaphore isolation does not generate new threads, so there is no switching back and forth between a large number of threads; but semaphore isolation also has disadvantages, it does not support timeout settings, so it is suitable for non-network requests.

2.2. Realize semaphore isolation

(1) Introduce dependencies

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

(2) Write Service layer code

Semaphore isolation is also annotated with [@HystrixCommand], and the specified isolation strategy is [semaphore isolation].

package com.gitcode.hystrix.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 19:49
 * @Copyright (C) ZhuYouBin
 * @Description: 信号量隔离
 */
@Service
public class HystrixSemaphoreService {

    @HystrixCommand(
            // 设置 hystrix 命令的属性
            commandProperties = {
                    // 设置线程池隔离的超时时间,默认是1000ms
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000"),
                    // 设置隔离策略是【信号量隔离】,默认是线程池隔离
                    @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"),
                    // 设置信号量最大请求数, 超过最大信号量数量,如果写了 fallbackMethod 属性,则会调用快速失败方法
                    @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "4")
            },
            // 设置快速失败时候调用的方法,可以写,也可以不写,写了就会执行快速失败,不写就阻塞等待
            fallbackMethod = "fallbackDemo"
    )
    public String queryList() {
        // TODO 这里模拟调用其他微服务
        System.out.println("微服务调用成功:" + Thread.currentThread().getName());
        return "success";
    }

    public String fallbackDemo() {
        System.out.println("接口调用失败,请稍后重试!");
        return "接口调用失败,请稍后重试!";
    }
}

(3) Write Controller layer code

package com.gitcode.hystrix.controller;

import com.gitcode.hystrix.service.HystrixSemaphoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @version 1.0.0
 * @Date: 2023/4/9 19:47
 * @Copyright (C) ZhuYouBin
 * @Description: Hystrix 信号量隔离
 */
@RestController
@RequestMapping("/hystrix/semaphore")
public class HystrixSemaphoreController {

    @Autowired
    private HystrixSemaphoreService hystrixSemaphoreService;

    @GetMapping("/queryList")
    public String queryList() {
        return hystrixSemaphoreService.queryList();
    }
}

(4) Run the test

Start the application, use jemeter to simulate concurrent requests, and view the console input log.

So far, Hystrix has introduced thread pool isolation and semaphore isolation.

In summary, this article is over. It mainly introduces the implementation of thread pool isolation and semaphore isolation by Hystrix of microservice components.

Guess you like

Origin blog.csdn.net/qq_39826207/article/details/130038440