Hystrix 请求合并、请求隔离、优化

请求合并

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.7.RELEASE</version>
</dependency>

<!-- lombok-->
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
</dependency>

启动类 加注解@EnableHystrix

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@SpringBootApplication
@EnableHystrix
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run (DemoApplication.class, args);
    }

}

service服务

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Component
@Slf4j
public class TestServcie {
    @HystrixCollapser(batchMethod = "getUserByIdBatch", //合并 请求方法
            scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,//请求 方式
            collapserProperties = {
                    // 间隔多久的请求会进行合并,默认是 10ms (时间限制)
                    @HystrixProperty(name = "timerDelayInMilliseconds", value = "15"),
                    // 批处理之前,批处理中允许的最 大请求数 (数量限制)
                    @HystrixProperty(name = "maxRequestsInBatch", value = "200"),
                    @HystrixProperty(name = "requestCache.enabled", value = "true")
            }
    )
    // 处理请求合并的方法一定 要支持异步!!,返回值必须是 Future<T>
    // 指出 方法的返回值,参数
    public Future<User> getUserById(Long id) {
        log.info ("------selectProductByIdReturnFuture------");
        return null;
    }


    /**
     * 因为是 合并请求,所以 返回值是 之前返回值的集合,参数 也是之前参数的的集合
     */
    // 声明 请求合并的方法
    @HystrixCommand
    public List<User> getUserByIdBatch(List<Long> ids) {
        log.info ("=====batch start ====");
        // TODO 对这些数据 批量处理!!
        List<User> users = ids.stream ().map (
                x -> {
                    User user = new User ();
                    user.setId (x);
                    user.setName ("name :" + x);
                    return user;
                }

        ).collect (Collectors.toList ());
        log.info ("=====batch end ,handle {} 条 request====", ids.size ());
        return users;
    }
}


测试

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
@Slf4j
public class RetryController {

    @Resource
    private TestServcie testServcie;

    @GetMapping("/test")
    public String getUser(long id) throws ExecutionException, InterruptedException {
        Future<User> f = testServcie.getUserById (id);
        System.out.println (f.get ());
        return "success";
    }

}


@Data
class User {
    private long id;
    private String name;

}

结果:

在这里插入图片描述

请求隔离

线程池隔离(大部分情况下)

之前请求缓存的例子中,并发的请求一个接口时,造成另一个接口耗时也增多,当时我们使用的缓存解决,还可以使用线程池隔离方式解决
在这里插入图片描述
而增加了隔离以后,两个接口隔离,即每个隔离粒度都是个线程池,互不干扰,异步方式提高了并发的性能
在这里插入图片描述
这种方式线程每次创建销毁切换等等都需要消耗CPU的性能,如果要隔离的实例太多了,成百上千个,也不推荐使用这种情况

信号量隔离

同步方式,阻塞我们 请求方的线程有一个信号量的概念,其实就是个计数器,当请求来的时候先拿到信号量,再执行,执行完释放

当信号量消耗完时其他的线程就阻塞等待或者快速释放
在这里插入图片描述
同步方式,不支持超时,无法用于网络。比如 系统内部的逻辑处理时可以使用

线程池隔离演示

引入依赖

<!--  hystrix   -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.7.RELEASE</version>
</dependency>

<!-- lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

启动类 加注解@EnableHystrix

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@SpringBootApplication
@EnableHystrix
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run (DemoApplication.class, args);
    }

}

service服务

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class TestServcie {
    // 声明需要服务容错的方法
    // 线程池隔离
    @HystrixCommand(
            commandKey = "getProductList",//接口名称,默认方法名
            threadPoolKey = "order-testServcie-Pool",//线程池名称,相同名称使用同一个线程池
            commandProperties = {
                    // 隔离策略
                    @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
                    //超时时间,默认1000ms, 超时 就走fallbackMethod 降级
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200")
            },
            threadPoolProperties = {

                    // 线程池核心线程大小
                    @HystrixProperty(name = "coreSize", value = "3"),
                    // 队列 等待阈值(最大队列长度,默认-1)
                    @HystrixProperty(name = "maxQueueSize", value = "10"),
                    // 线程存活时间,默认 1min
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    // 超出队列 等待阈值 执行拒绝策略!!
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "10"),

            }, fallbackMethod = "fallbackMtd"
    )
    public String getProductList() {
        log.info (Thread.currentThread ().getName () + "---getProductList----");

        return "success";
    }

    /**
     * 超出队列等待阈值执行方法
     **/
    private String fallbackMtd() {
        log.info (Thread.currentThread ().getName () + "---降级sorry, the request is timeout----");
        return "降级sorry, the request is timeout";
    }


}

测试

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class RetryController {

    @Resource
    private TestServcie testServcie;

    @GetMapping("/test")
    public String getUser() {
        return testServcie.getProductList ();
    }

}

结果:

在这里插入图片描述

信号量隔离演示

其他不变 修改TestServcie

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class TestServcie {
    //信号量隔离
    @HystrixCommand(commandProperties = {
            //超时时间,默认1000ms
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200"),
            //信号量隔离
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),
            //信号量最大并发,调小一点方便模拟高并发
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "6")
    }, fallbackMethod = "fallbackMtd")
    public String getProductList() {
        log.info (Thread.currentThread ().getName () + "---getProductList----");

        return "success";
    }

    /**
     * 超出队列等待阈值执行方法
     **/
    private String fallbackMtd() {
        log.info (Thread.currentThread ().getName () + "---降级sorry, the request is timeout----");
        return "降级sorry, the request is timeout";
    }


}

结果:

在这里插入图片描述

Hystrix的其他用法

SpringCloud优化记录

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值