战到这,说完sentinel,springcloud主流组件基本就整合总结完了,接下来就要实战了,原谅自己8月份又不能看微容器和逆向了。感觉也没办法,伏天里真是让人心烦意乱,干啥事都没啥效率,想下周回家休整几天但是因为疫情也暂且搁置了吧,一切以大局为重,只希望下周不要再下雨了,好久没有踢球了😩
1、Sentinel 流量卫兵
替代耐非豪猪,强无敌的集流控、降级、负载保护等于一身的一个组件,毕竟能顶住双11大促压力的东西谁敢说不行?相关概念,在他的github wiki上写的很全:
和豪猪差不多,sentinel也分为自身的sever和仪表盘。仪表盘是个jar包,启动即可,然后将sentinel依赖引入微服务,配置文件开启sentinel并且写明仪表盘启动端口、与仪表盘通信端口即可完成可视化。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
# 开启sentinel 保护
spring.cloud.sentinel.enabled=true
# 指定sentinel dashboard web地址 连接dashboard
spring.cloud.sentinel.transport.dashboard=localhost:8080
# 指定sentinel组件与sentinel dashboard组件通信地址
spring.cloud.sentinel.transport.port=8719
写接口测试:
package com.jin.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author jinyunlong
* @date 2021/7/29 9:42
* @profession ICBC锅炉房保安
*/
@RestController
public class DemoController {
@GetMapping("/demo")
public String demo(){
System.out.println("demo ok....");
return "demo ok";
}
@GetMapping("/rongduan")
public String rongduan(Integer id) throws Exception {
System.out.println("id:"+id);
if(id<0) {
throw new Exception();
}
return "id"+id;
}
@GetMapping("/redian") //blockHandler 使用sentinel进行不同规则控制时的默认处理方案 fallback:自定义业务出错时默认处理方案 defaultFallback 指定一个业务错误时默认方案
@SentinelResource(value = "aaaa",blockHandler = "blockHandler",fallback = "fall") //作用代表这是一个sentinel资源
public String redian(Integer id) throws Exception {
System.out.println("id:"+id);
if(id<0) {
Exception e = new Exception();
System.out.println(e.getMessage());
throw e;
}
return "id"+id;
}
public String fall(Integer id){
return "服务器出错了";
}
public String blockHandler(Integer id, BlockException e){
if(e instanceof FlowException){
return "当前请求过于火爆,您已被流控";
}
if(e instanceof DegradeException){
return "当前请求过于火爆,您已被降级";
}
if(e instanceof ParamFlowException){
return "当前请求过于火爆,您已被热点参数限流";
}
return "服务器快爆了,请稍后再试";
}
}
注意:项目启动后如果不做接口的调用是不会被仪表盘发现的,因为sentinel是延迟加载,必须调用一次后才可以初始化。如下图,调用后可显示监控数据,可设置的规则很多,要想把这些全玩明白还是要结合实战才行,这里就先记画圈的那三个规则吧。也比较好理解:
流控规则:
流控规则分QPS流控和线程数流控,QPS(每秒的请求量)流控就是比如我把阈值设为1,每秒的请求数如果超过1就被限流了。线程数流控比如当请求A过来访问该接口,该请求处理的很慢,还没有返回数据;此时请求B也过来访问该接口,这个时候处理请求B需要额外开启一个线程,请求B则会报错;(这是在模式和效果都设置成直接失败的情况下),线程数流控是不能设置流控效果的要注意
流控模式和流控效果概念截图,就不一个一个试了,遇到具体情况再说;
QPS的流控直接失败很直观,线程数可以用Jmeter去进行测试
降级规则其实和豪猪的熔断差不多了。但是豪猪的熔断器好像没法自定义设置吧,sentinel却可以自定义时间了
可以参照rongduan接口代码给id值送一个负数进行尝试,概念:
有个比较关键的注解,参考下头的注释,这个注解的value值才是仪表盘配置规则的资源一定要注意!!
用热点规则来试一下,热点规则可以对接口参数进行流控
@SentinelResource(value = "aaaa",blockHandler = "blockHandler",fallback = "fall") //作用代表这是一个sentinel资源
//blockHandler 使用sentinel进行不同规则控制时的默认处理方案 fallback:自定义业务出错时默认处理方案 defaultFallback 指定一个业务错误时默认方案
然后基于redian接口的代码和热点规则的设置,正常返回、业务类异常、热点限流异常分别会有如下返回,要参照代码内容来看:
试了三个规则,可以通过设置生效就很简单(所以这块都是在贴图贴图贴图,烦内),但是实际的业务如果复杂起来这块绝对会变得复杂的多,所以说sentinel这块要是玩明白了(真太难了),微服务这块基本就没问题了。
2、整合复习
重写了一个父模块整合了几个微服务,由于nacos和sentinel的存在,所以父模块最后可以简化成为只有微服务和gateway模块,微服务中只需要配置nacos、sentinel、openfeign就可以了,代码挺好写。总结一个版本问题的深坑:
之前在写用nacos做配置中心时,由于springboot还是springcloud版本低读不到@value还是加载不到bootstrap.properties来着,然后就都升级了,之后就没问题了,但是在重写项目时又因为项目版本过高导致使用openfeign时出了问题,百度上好多解决方案也不靠谱,以下是我自己瞎试出来的一个解决方案,有待修改:剔除了ribbon 使用了spring-cloud-loadbalancer3.0.0版本(很奇怪为啥3.0.2pom一直会提示有错),最终可以实现(各个模块都能正常启动运行)的微服务pom和父模块版本控制pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_alibaba_parent</artifactId>
<groupId>com.jin</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud_alibaba_users</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>3.0.0</version>
</dependency>
<!--引入nacos client的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--引入sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--引入配置中心依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--读取bootstrap配置文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.jin</groupId>
<artifactId>springcloud_alibaba_parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springcloud_alibaba_commons</module>
<module>springcloud_alibaba_users</module>
<module>springcloud_alibaba_products</module>
<module>springcloud_alibaba_gateway</module>
</modules>
<properties>
<!--定义版本号-->
<spring.cloud.version>2020.0.2</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.3.RELEASE</spring.cloud.alibaba.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!--继承springboot父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<!--维护依赖-->
<dependencyManagement>
<!--维护springcloud-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--维护springcloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
该问题有待修改解决,看看接下来的springcloud实战(要开新坑了)有啥好方案吧。