配置Sentinel Server端可视化界面

下载Sentinel

下载完成后

springcloud 集群 docker 部署_spring cloud


运行以下代码

java -jar sentinel-dashboard-1.8.3.jar

运行后的结果

springcloud 集群 docker 部署_微服务_02


访问 localhost:8080 出现如下界面

*账号:sentinel *

*密码:sentinel *

springcloud 集群 docker 部署_开发语言_03

代码配置部分

普通搭建(2种方法)

查看nacos搭建

消费者导入sentinel的jar包

<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

编写application.yml配置文件

#端口
server:
  port: 7781

#服务名
spring:
  application:
    name: user-consumer-sentine

#    注册到Nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

    sentinel:
#      开启sentinel
      enabled: true
      transport:
#        将服务配置到sentinel中
        dashboard: localhost:8080

resttemplate:
  sentinel:
    #        开启ribbon与sentinel整合
    enabled: true

编写Controller层

@Slf4j // lombok包
@RestController
@RequestMapping("/sentinel")
public class UserController {

    @Resource
    RestTemplate restTemplate;

    @RequestMapping("/getUser/{id}")
    /**
     * blockHandler 异常降级后处理的方法
     * blockHandlerClass 异常降级后处理的类
     * fallback 限流熔断后处理的方法
     * fallbackClass 限流熔断后处理的类
     */
    @SentinelResource(
            fallback = "handleFallback", fallbackClass = EarsSentinelCompilations.class,
            blockHandler = "handleBlock", blockHandlerClass = EarsSentinelCompilations.class
    )
    public TbUser findById(@PathVariable Integer id){
        String url = "http://user-provider/user/find/"+id;
        TbUser forObject = restTemplate.getForObject(url, TbUser.class);
        log.info(String.valueOf(forObject));
        return forObject;
    }
}

@SentinelResource:
blockHandler: 异常降级后处理的方法
blockHandlerClass: 异常降级后处理的类
fallback: 限流熔断后处理的方法
fallbackClass: 限流熔断后处理的类

编写Sentinel熔断降级处理类

public class EarsSentinelCompilations {

//    异常
    public static TbUser handleFallback(@PathVariable("id") Integer id){
        return TbUser.builder().id(-1).name("Ribbon兜底").note("异常报错").build();
    }
//   非异常
    public static TbUser handleBlock(@PathVariable("id") Integer id){
        return TbUser.builder().id(-1).name("Ribbon兜底兜底").note("非异常报错").build();
    }
}

编写启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class UserSentinelApplication7781 {
    public static void main(String[] args) {
        SpringApplication.run(UserSentinelApplication7781.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

运行Nacos,运行Sentienl,运行启动类
为了测试效果:给服务提供者写一个报错

@Slf4j
@RestController
@RequestMapping("user")
public class UserController {

    @Resource
    UserService userService;

    @SneakyThrows
    @RequestMapping("find/{id}")
    public TbUser findById(@PathVariable Integer id){
        log.info("provide:id:"+id);
        /*测试远程调用的超时时间
        Thread.sleep(4000);*/
//        int i = 1/0;
        return userService.getUserId(id);
    }
}

结果如下:

springcloud 集群 docker 部署_微服务_04


成功进入降级处理方法

第二种方法

对注入的Restemplate的注解上加,@SentinelRestTemplate
@Bean
    @LoadBalanced
    @SentinelRestTemplate(
            fallback = "handleFallback", fallbackClass = EarsSentinelRestTemplate.class,
            blockHandler = "handleBlock", blockHandlerClass = EarsSentinelRestTemplate.class
    )
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
新建一个处理熔断降级的类
public class EarsSentinelRestTemplate {
    /**
     * 静态方法
     *      返回值: SentinelClientHttpResponse
     *      参数 : request , byte[] , clientRquestExcetion , blockException
     */
    //限流熔断
    public static SentinelClientHttpResponse handleBlock(HttpRequest request, 
                                                         byte[] body, 
                                                         ClientHttpRequestExecution execution, 
                                                         BlockException ex) {
        return new SentinelClientHttpResponse("熔断");
    }
    //异常降级
    public static SentinelClientHttpResponse handleFallback(HttpRequest request, 
                                                            byte[] body,
                                                            ClientHttpRequestExecution execution, 
                                                            BlockException ex) {
        return new SentinelClientHttpResponse("降级");
    }
}

使用可视化界面设置限流

由于免费版的,重启服务消费者设置的限流规则就会消失,持久化保存限流规则,需要使用企业版

侧边栏选择:簇点链路 > 选择 /sentinel/getUser/{id}

springcloud 集群 docker 部署_微服务_05


/sentinel/getUser/{id} 添加一个规则

springcloud 集群 docker 部署_开发语言_06

阈值类型:
QPS(每秒查询率 Query Per Second) :每秒的响应请求数
线程数

流控模式:
直接: 流控模式:最简单的模式,只要超过单机阈值就对资源名(接口url)进行限流。
关联: 流控模式:需要设置资源名(例如/res1)和关联资源(例如/res2),若关联资源/res2超过单机阈值,则/res1被限流(res2不会被限流)。
链路: 流控模式:当从某个接口过来的资源达到限流条件时,开启限流

流控效果:
快速失败: 直接拒绝请求。
Warm Up(预热): 需设置预热时长(单位秒),假设为5,则效果就是前五秒请求资源名时,单机阈值始终为1,5秒后,阈值恢复到正常值,即设定的值。(服务刚启动时,各个性能指标均未达到巅峰,此时不易处理过多的请求,这种情况就可以使用预热。打个比方,就好比早上刚起床,还比较困,但随着时间的推移,工作学习效率也逐渐提高了,能够处理更复杂的任务)。
排队等待: 需设置预热时长(单位毫秒,假设为300),当请求的资源超过单机阈值时,不会立马抛异常,会在0.3秒后再次请求该资源,若能调通,则不抛异常,否则抛出异常。

测试

springcloud 集群 docker 部署_微服务_07

使用 Jmeter 对API进行压力测试

springcloud 集群 docker 部署_spring cloud_08


设置10个线程,1秒类完成,永久运行,记得测试完后关闭

springcloud 集群 docker 部署_spring cloud alibaba_09


启动后压力测试后访问这个API

springcloud 集群 docker 部署_微服务_10


响应结果

Blocked by Sentinel (flow limiting) 被Sentinel阻塞(限流)

使用Feign调用 (3种方法)

导入opfeign的jar文件

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

第一种普通使用

编写feign接口

@FeignClient("user-provider")
public interface FeignService {

    @GetMapping("user/find/{id}")
    TbUser findById(@PathVariable("id") Integer id);
}

编写处理熔断降级类

/**
 * 普通兜底类
 */
public class EarsSentinelCompilations {

//  降级处理
    public static TbUser handleFallback(@PathVariable("id") Integer id){
        return TbUser.builder().id(-1).name("整合feign的普通兜底").note("异常报错").build();
    }
//  熔断处理
    public static TbUser handleBlock(@PathVariable("id") Integer id){
        return TbUser.builder().id(-1).name("整合feign的普通兜底").note("非异常报错").build();
    }
}

第二种 单独降级处理

编写feign接口

//指定的伪客户端接口的回退类。 回退类必须实现由该注释注释的接口,并且是一个有效的spring bean
@FeignClient(value = "user-provider",fallback = FeignServiceImpl.class)
@FeignClient("user-provider")
public interface FeignService {

    @GetMapping("user/find/{id}")
    TbUser findById(@PathVariable("id") Integer id);
}

编写处理降级类

/**
 *客户端接口的回退类
 */
//@Component
public class FeignServiceImpl implements FeignService {
    @Override
    public TbUser findById(Integer id) {
        return TbUser.builder().id(-1).name("整合feign的回退兜底").note("异常报错").build();
    }
}

第三种 单独熔断处理

编写feign接口

//为指定的Feign客户端接口定义一个备用工厂。 回退工厂必须生成回退类的实例,这些实例实现了由FeignClient标注的接口。 回退工厂必须是一个有效的spring bean。
@FeignClient(value = "user-provider",fallbackFactory = FeignServiceBeanImpl.class)
@FeignClient("user-provider")
public interface FeignService {

    @GetMapping("user/find/{id}")
    TbUser findById(@PathVariable("id") Integer id);
}

编写处理熔断类

/**
 * Feign客户端接口定义一个备用工厂
 */
@Slf4j
@Component
public class FeignServiceBeanImpl implements FallbackFactory<FeignService> {
    @Override
    public FeignService create(Throwable cause) {
        log.info(String.valueOf(cause));
        return (message) -> {
            log.info(String.valueOf(message));
            return TbUser.builder().id(-1).name("整合feign的工厂兜底").note("异常报错").build();
        };
    }
}

编写Controller

@Slf4j // lombok:的包
@RestController
@RequestMapping("/sentinel")
public class UserController {

    @Resource
    FeignService feignService;

    @RequestMapping("/feign/getUser/{id}")
    /**
     * blockHandler 异常降级后处理的方法
     * blockHandlerClass 异常降级后处理的类
     * fallback 限流熔断后处理的方法
     * fallbackClass 限流熔断后处理的类
     */
    @SentinelResource(
            fallback = "handleFallback", fallbackClass = EarsSentinelCompilations.class,
            blockHandler = "handleBlock", blockHandlerClass = EarsSentinelCompilations.class
    )
    public TbUser findById(@PathVariable Integer id){
//        使用feign调用
        TbUser tbUser = feignService.findById(id);
        log.info(String.valueOf(tbUser));
        return tbUser;
    }
}

编写application.yml配置文件

#端口
server:
  port: 7781

#服务名
spring:
  application:
    name: user-consumer-sentine

#    注册到Nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

    sentinel:
#      开启sentinel
      enabled: true
      transport:
#        将服务配置到sentinel中
        dashboard: localhost:8080

#        开启feign和sentinel的整合
feign:
  sentinel:
    enabled: true

编写启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableFeignClients
public class UserSentinelFeignApplication7782 {
    public static void main(String[] args) {
        SpringApplication.run(UserSentinelFeignApplication7782.class,args);
    }
}