Depth Hystrix isolated interface thread pool limiting _ a little class (multi-shore College)

Depth Hystrix thread pool limiting isolated interfaces

Speaking in front of the request cache request buffer Hystrix, fallback graceful degradation, circuit breaker breaker fast-acting, this lecture, we explain in detail Hystrix thread pool limiting isolated interfaces.
Here Insert Picture Description

Hystrix thread pool is full or by determining the amount of signal, exceeds the request capacity, go directly Reject degraded, so as to achieve a limiting role.

Current limit is to limit the amount of access to backend services, for example, you limit the resources MySQL, Redis, Zookeeper and various other back-end middleware access, in fact, it is to avoid too much traffic directly killed by the back-end services .

Design thread pool isolation technology

Hystrix using Bulkhead Partition bulkheads isolation technology to rely on external resource isolation, and thus avoid any malfunction of external dependencies cause the service to crash.

Isolation bulkhead , the interior space of the hull is to say the segment divided into several compartments, once a few compartments breakage water, the water will not flow therebetween each other, this way damaged when the ship still can have sufficient buoyancy and stability, and further reduce the risk of immediate wreck.
Here Insert Picture Description

Hystrix dependence on external each with a separate thread pool, so, if reliance on the external call delay is very serious, is the most depleted that rely on their own thread pool only, does not affect other dependent calls.

Scene Hystrix application thread pool mechanism

  • Each service will call dozens of back-end services depend on, rely on those back-end services are often composed of many different teams development.
  • Each backend dependent services will provide its own client call the library, for example, with thrift, it would provide the corresponding thrift dependence.
  • client call the library at any time to change.
  • client call the library at any time may add a new logical network requests.
  • client library may contain information such as call automatically retry, data analysis, and other logic in the cache memory.
  • client library calls are generally of the caller is a black box, including implementation details, network access, the default configuration and so on.
  • In a real production environment, the caller often occur suddenly surprised to find, client call the library undergone some changes.
  • 即使 client 调用库没有改变,依赖服务本身可能有会发生逻辑上的变化。
  • 有些依赖的 client 调用库可能还会拉取其他的依赖库,而且可能那些依赖库配置的不正确。
  • 大多数网络请求都是同步调用的。
  • 调用失败和延迟,也有可能会发生在 client 调用库本身的代码中,不一定就是发生在网络请求中。

简单来说,就是你必须默认 client 调用库很不靠谱,而且随时可能发生各种变化,所以就要用强制隔离的方式来确保任何服务的故障不会影响当前服务。

线程池机制的优点

  • 任何一个依赖服务都可以被隔离在自己的线程池内,即使自己的线程池资源填满了,也不会影响任何其他的服务调用。
  • 服务可以随时引入一个新的依赖服务,因为即使这个新的依赖服务有问题,也不会影响其他任何服务的调用。
  • 当一个故障的依赖服务重新变好的时候,可以通过清理掉线程池,瞬间恢复该服务的调用,而如果是 tomcat 线程池被占满,再恢复就很麻烦。
  • 如果一个 client 调用库配置有问题,线程池的健康状况随时会报告,比如成功/失败/拒绝/超时的次数统计,然后可以近实时热修改依赖服务的调用配置,而不用停机。
  • 基于线程池的异步本质,可以在同步的调用之上,构建一层异步调用层。

简单来说,最大的好处,就是资源隔离,确保说任何一个依赖服务故障,不会拖垮当前的这个服务。

线程池机制的缺点

  • 线程池机制最大的缺点就是增加了 CPU 的开销。

    除了 tomcat 本身的调用线程之外,还有 Hystrix 自己管理的线程池。
  • 每个 command 的执行都依托一个独立的线程,会进行排队,调度,还有上下文切换。
  • Hystrix 官方自己做了一个多线程异步带来的额外开销统计,通过对比多线程异步调用+同步调用得出,Netflix API 每天通过 Hystrix 执行 10 亿次调用,每个服务实例有 40 个以上的线程池,每个线程池有 10 个左右的线程。)最后发现说,用 Hystrix 的额外开销,就是给请求带来了 3ms 左右的延时,最多延时在 10ms 以内,相比于可用性和稳定性的提升,这是可以接受的。

我们可以用 Hystrix semaphore 技术来实现对某个依赖服务的并发访问量的限制,而不是通过线程池/队列的大小来限制流量。

semaphore 技术可以用来限流和削峰,但是不能用来对调研延迟的服务进行 timeout 和隔离。

execution.isolation.strategy 设置为 SEMAPHORE,那么 Hystrix 就会用 semaphore 机制来替代线程池机制,来对依赖服务的访问进行限流。如果通过 semaphore 调用的时候,底层的网络调用延迟很严重,那么是无法 timeout 的,只能一直 block 住。一旦请求数量超过了 semaphore 限定的数量之后,就会立即开启限流。

接口限流 Demo

假设一个线程池大小为 8,等待队列的大小为 10。timeout 时长我们设置长一些,20s。

在 command 内部,写死代码,做一个 sleep,比如 sleep 3s。

  • withCoreSize:设置线程池大小
  • withMaxQueueSize:设置等待队列大小
  • withQueueSizeRejectionThreshold:这个与 withMaxQueueSize 配合使用,等待队列的大小,取得是这两个参数的较小值。

如果只设置了线程池大小,另外两个 queue 相关参数没有设置的话,等待队列是处于关闭的状态。

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()
                        // 设置线程池大小为8
                        .withCoreSize(8)
                        // 设置等待队列大小为10
                        .withMaxQueueSize(10)
                        .withQueueSizeRejectionThreshold(12))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withCircuitBreakerEnabled(true)
                        .withCircuitBreakerRequestVolumeThreshold(20)
                        .withCircuitBreakerErrorThresholdPercentage(40)
                        .withCircuitBreakerSleepWindowInMilliseconds(3000)
                        // 设置超时时间
                        .withExecutionTimeoutInMilliseconds(20000)
                        // 设置fallback最大请求并发数
                        .withFallbackIsolationSemaphoreMaxConcurrentRequests(30)));
        this.productId = productId;
    }

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

        if (productId == -1L) {
            throw new Exception();
        }

        // 请求过来,会在这里hang住3秒钟
        if (productId == -2L) {
            TimeUtils.sleep(3);
        }

        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;
    }
}

We simulated 25 requests. 8 before the request will be directly hang 3s when live call interface, then subsequent requests 10 will first wait for a request to enter the waiting queue in front of the execution is completed. The last seven requests over, will directly reject, call fallback downgrade logic.

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

    @Test
    public void testReject() {
        for (int i = 0; i < 25; ++i) {
            new Thread(() -> HttpClientUtils.sendGetRequest("http://localhost:8080/getProductInfo?productId=-2")).start();
        }
        // 防止主线程提前结束执行
        TimeUtils.sleep(50);
    }
}

From the results, we can clearly see that the print out of a total of 7 downgrade merchandise. This is the result of the request exceeds + number of queues and thread pools to directly reject.

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)
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)
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)
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)
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)
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)
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
调用接口查询商品数据,productId=-2
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": -2, "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}
// 后面都是一些正常的商品信息,就不贴出来了
//...

[Thank you for reading, if we can help you, trouble spots a praise ~]

More experience and technology come together to welcome the exchange of learning:
a little classroom - for the dream fight online learning platform http://www.yidiankt.com/

[Number of public attention, to receive free - java core knowledge [point]]
No public concern, to receive free - java core knowledge [point]
QQ discussion group: 616 683 098
QQ: 3,184,402,434
want in-depth study of students learning together can add my QQ discussion - there is a full set of resources to share, discuss experiences, so you oh !
Here Insert Picture Description

Guess you like

Origin www.cnblogs.com/yidiankt/p/11458148.html