開源地址:
ma/springcloud-alibaba-demo
簡(jiǎn)介
參考:https://www.cnblogs.com/zys2019/p/12682628.html
SpringBoot、SpringCloud 、SpringCloud Alibaba 以及各種組件存在版本對(duì)應(yīng)關(guān)系??蓞⒖枷旅?/p>
版本對(duì)應(yīng)
項(xiàng)目前期準(zhǔn)備
啟動(dòng)nacos.? ?./startup.cmd -m standalone?
登陸nacos官方 localhost:8848? ?nacos/nacos
創(chuàng)建父工程spring-cloud-alibaba
pom.xml如下:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lgc</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cloud-alibaba-consumer80</module>
<module>cloud-alibaba-provider8081</module>
<module>cloud-alibaba-provider8082</module>
<module>cloud-alibaba-sentinel</module>
<module>cloud-alibaba-config-client</module>
<module>cloud-alibaba-getway</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.boot.version>2.2.2.RELEASE</spring.boot.version>
<spring.cloud.alibaba.version>2.2.0.RELEASE</spring.cloud.alibaba.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
</properties>
<!-- 依賴管理,父工程鎖定版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--<fork>true</fork>-->
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
Nacos
Nacos集成了Ribbon實(shí)現(xiàn)了負(fù)載均衡。
創(chuàng)建服務(wù)提供者子模塊cloud-alibaba-provider8001
pom.xml如下
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lgc</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloud-alibaba-provider8081</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--springcloud alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
application.yml如下
server:
port: 8001
spring:
application:
name: cloud-alibaba-nacos-provider
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
management:
endpoints:
web:
exposure:
include: "*"
?其中management這一段是屬于端口暴露
創(chuàng)建啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
public class CloudAlibabaProvider8081Application {
public static void main(String[] args) {
SpringApplication.run(CloudAlibabaProvider8081Application.class, args);
}
}
Nacos注冊(cè)服務(wù)需要在啟動(dòng)類中加上@EnableDiscoveryClient,意思就是服務(wù)注冊(cè)發(fā)現(xiàn)
創(chuàng)建controller接口
@RestController
public class UserController {
@Value("${server.port}")
private int port;
@GetMapping("/user/get")
public String get(){
return "provider port is :"+port;
}
}
這樣去取server.port是從application.yml去取。
啟動(dòng)服務(wù)提供者,在nacos界面上就能看到服務(wù)已經(jīng)注冊(cè)進(jìn)來了。
同理,創(chuàng)建cloud-alibaba-provider8002,端口為8002.啟動(dòng)后發(fā)現(xiàn)nacos的集群的實(shí)例數(shù)為2.
OpenFeign
創(chuàng)建服務(wù)調(diào)用實(shí)例
創(chuàng)建服務(wù)消費(fèi)者子模塊cloud-alibaba-consumer80
pom.xml如下
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lgc</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<version>1.0-SNAPSHOT</version>
<artifactId>cloud-alibaba-consumer80</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--springcloud alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
application.yml如下
server:
port: 80
spring:
application:
name: cloud-alibaba-nacos-consumer
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
feign:
client:
#指定全局
default:
#連接超時(shí)時(shí)間
connectTimeout: 5000
#服務(wù)等待時(shí)間
readTimeout: 5000
loggerLevel: full
logging:
level:
com.lgc.cloudalibabaconsumer80.client: debug
需要把consumer這個(gè)服務(wù)也放到nacos中,就像把這些服務(wù)放到一個(gè)大容器中,大容器的服務(wù)之間可以相互調(diào)用、
創(chuàng)建啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class CloudAlibabaConsumer80Application {
public static void main(String[] args) {
SpringApplication.run(CloudAlibabaConsumer80Application.class, args);
}
}
@EnableFeignClients這個(gè)代表當(dāng)前服務(wù)作為OpenFeign客戶端。
創(chuàng)建Client接口,用于端口映射,可以調(diào)用其他服務(wù)中的接口(接口在其他服務(wù)中已存在)
@FeignClient(value = "cloud-alibaba-nacos-provider")
public interface UserClient {
@GetMapping("/user/get")
String get();
}
@FeignClient中 的Value值為目標(biāo)服務(wù)的名字,也就是目標(biāo)服務(wù)的spring.application.name
接口的路由也得對(duì)應(yīng)上目標(biāo)服務(wù)的請(qǐng)求url,也就是說cloud-alibaba-nacos-provider的controller中也有個(gè)/user/get的接口才可以。
創(chuàng)建controller
@RestController
@RequestMapping("/consumer")
public class UserController {
@Autowired
private UserClient userClient;
@GetMapping("/get")
public String get() {
return userClient.get();
}
}
啟動(dòng)服務(wù),在nacos中就可以看到
訪問localhost:80/consumer/get,看到的是8001和8002在進(jìn)行輪訓(xùn)負(fù)載,因?yàn)閚acos默認(rèn)支持負(fù)載均衡,原因是他默認(rèn)引入了ribbon.
為了引入nacos的動(dòng)態(tài)參數(shù),我們新建一個(gè)cloud-alibaba-config-client模塊,pom.xml如下
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-cloud-alibaba</artifactId>
<groupId>com.lgc</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloud-alibaba-config-client</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--springcloud alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
</project>
新建bootstrap.yml:系統(tǒng)級(jí)別的配置,主要配置配置中心的相關(guān)信息,優(yōu)先加載
spring:
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
config:
server-addr: ${spring.cloud.nacos.server-addr}
file-extension: yaml
group: DEFAULT_GROUP
#namespace: 5a2f851c-8639-4acb-98f1-d5e76cd46457
management:
endpoints:
web:
exposure:
include: '*'
?值得一提的是namespace填的是Id,而不是你新建的命名空間的漢字名稱。
application.yml如下
spring: application: name: nacos-config-client profiles: # active: dev #開發(fā)環(huán)境 # active: test 測(cè)試環(huán)境 active: info #info??
注意一下這里的profiles選的是info級(jí)別,那么在加載nacos的配置文件的時(shí)候是以info為后綴的。
創(chuàng)建啟動(dòng)類
?
@SpringBootApplication
@EnableDiscoveryClient
public class CloudAlibabaConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(CloudAlibabaConfigClientApplication.class, args);
}
}
創(chuàng)建controller接口
@RestController
@RefreshScope //類上加了@RefreshScope注解,用于自動(dòng)刷新。若不添加,則無法進(jìn)行自動(dòng)的配置刷新
public class UserController {
@Value("${config.info}")
private String info;
@GetMapping("/config/get")
public String get() {
return "The config info is :" + info;
}
}
@RefreshScope用于參數(shù)的自動(dòng)刷新,如果你nacos中的配置更改,能夠自動(dòng)同步過來,不需要再重啟服務(wù)。
nacos中的配置文件命名規(guī)則為:${prefix}-${spring.profile.active}.${file-extension}。
prefix :默認(rèn)為 spring.application.name 的值,也可以通過配置項(xiàng) spring.cloud.nacos.config.prefix來配置。
spring.profile.active :即為當(dāng)前環(huán)境對(duì)應(yīng)的 profile。
file-exetension: 為配置內(nèi)容的數(shù)據(jù)格式,可以通過配置項(xiàng) spring.cloud.nacos.config.file-extension 來配置。目前只支持 properties 和 yaml 類型。
假如spring.application.name=nacos-config-client
,環(huán)境為dev,后綴名是yaml,那么dataID就是nacos-config-client-dev.yaml
。這里不存在主/從配置文件的說法,只指定不同環(huán)境的配置,公共的配置都放在自己的環(huán)境中。另外,dataId后綴必須是yaml或properties。
測(cè)試
啟動(dòng)3344,訪問http://localhost:3344/config/get,可以看到配置的信息。然后修改配置中的config.info
內(nèi)容,再刷新頁面,發(fā)現(xiàn)配置信息也更新了。此時(shí)就做到了配置實(shí)時(shí)刷新。
Gatway
新建cloud-alibaba-gatway模塊
pom.xml如下
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.lgc</groupId>
<artifactId>spring-cloud-alibaba</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloud-alibaba-getway</artifactId>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--服務(wù)網(wǎng)關(guān)-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
</project>
application.yml如下
server:
port: 7001
spring:
application:
name: cloud-gateway-service
cloud:
nacos:
server-addr: localhost:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
#namespace: 5a2f851c-8639-4acb-98f1-d5e76cd46457
gateway:
routes:
- id: provide
uri: lb://cloud-alibaba-nacos-provider
predicates:
- Path=/user/**
- id: consumer
uri: lb://cloud-alibaba-nacos-consumer
predicates:
- Path=/consumer/**
management:
endpoints:
web:
exposure:
include: '*'
?lb:代表loadbalance負(fù)載均衡
lb://cloud-alibaba-nacos-provider? ? 目標(biāo)cloud-alibaba-nacos-provider服務(wù)
攔截請(qǐng)求/user/**? ? 攔截/user下的所有請(qǐng)求,指向cloud-alibaba-nacos-provider服務(wù)。
創(chuàng)建啟動(dòng)類
@SpringBootApplication
public class CloudAlibabaGetwayApplication {
public static void main(String[] args) {
SpringApplication.run(CloudAlibabaGetwayApplication.class, args);
}
}
Sentinel
下載地址Releases · alibaba/Sentinel · GitHub,選擇對(duì)應(yīng)的版本下載即可。這里以1.8.2版本為例
可以下載壓縮包,也可以直接下載jar。本章節(jié)在Windows中說明,就直接下載jar進(jìn)行說明。
下載到本地執(zhí)行
java -jar sentinel-dashboard-1.7.2.jar
在瀏覽器訪問http://localhost:8080? ?sentinel/sentinel
登錄后看到儀表盤是空的,因?yàn)楝F(xiàn)在沒有監(jiān)控任何的服務(wù)。
創(chuàng)建cloud-alibaba-sentinel模塊
pom.xml如下
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-cloud-alibaba</artifactId>
<groupId>com.lgc</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>cloud-alibaba-sentinel</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--springcloud alibaba nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--springcloud alibaba sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--springcloud alibaba sentinel-datasource-nacos-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
</dependencies>
</project>
application.yml如下
server:
port: 8401
spring:
application:
name: cloud-alibaba-sentinel-service
cloud:
nacos:
server-addr: 127.0.0.1:8848
discovery:
server-addr: ${spring.cloud.nacos.server-addr}
sentinel:
transport:
# sentinel dashboard的地址
dashboard: 127.0.0.1:8080
# sentinel dashboard內(nèi)部通信端口,默認(rèn)為8719,如果被占用會(huì)自動(dòng)+1,直到找到為止
port: 8719
management:
endpoints:
web:
exposure:
include: "*"
創(chuàng)建啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
public class CloudAlibabaSentinelApplication {
public static void main(String[] args) {
SpringApplication.run(CloudAlibabaSentinelApplication.class, args);
}
}
創(chuàng)建controller
?
package com.zys.cloud.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController {
@GetMapping("/testA")
public String testA(){
return "--------testA";
}
@GetMapping("/testB")
public String testB(){
return "--------testB";
}
}
測(cè)試。先啟動(dòng)nacos服務(wù),再啟動(dòng)sentinel服務(wù),再啟動(dòng)8401。訪問http://localhost:8401/testA后會(huì)在儀表盤看到生成了一個(gè)服務(wù):
主要講解:流控,熔斷,熱點(diǎn),授權(quán)
其中QBS表示1秒的請(qǐng)求數(shù),QPS表示1秒的拒絕請(qǐng)求數(shù)。
流控
流量控制(flow control),其原理是監(jiān)控應(yīng)用流量的QPS或并發(fā)線程數(shù)等指標(biāo),當(dāng)達(dá)到指定的閾值時(shí)對(duì)流量進(jìn)行控制,以避免被瞬時(shí)的流量高峰沖垮,從而保障應(yīng)用的高可用性。
QPS表示每秒的請(qǐng)求數(shù)。可在簇點(diǎn)鏈路中選擇鏈路的點(diǎn)擊流控按鈕添加,也可在流控規(guī)則中添加。其他的功能類似。這里以/testA的流控為例:
上圖的配置,也就是說對(duì)于請(qǐng)求/testA,當(dāng)每秒請(qǐng)求的次數(shù)超過閾值,那么會(huì)直接返回失敗的信息。保存后顯示列表如下:
訪問localhost:8401/testA結(jié)果是正常的,若快速的刷新幾次,會(huì)發(fā)現(xiàn)返回了流控的信息:
對(duì)于針對(duì)來源,默認(rèn)使用default,那么也可以指定來源,那么當(dāng)指定的這個(gè)來源調(diào)用/testA請(qǐng)求時(shí)會(huì)進(jìn)行流控,其他服務(wù)調(diào)用/testA時(shí)不進(jìn)行流控,也就是對(duì)來源進(jìn)行針對(duì)性的流控。
也可設(shè)置并發(fā)線程的閾值,當(dāng)某一時(shí)刻并發(fā)線程數(shù)量超過時(shí)會(huì)進(jìn)行流控。
使用Jmeter對(duì)/testA發(fā)送超過閾值的并發(fā)請(qǐng)求,那么在發(fā)送的同時(shí)再訪問/testA就會(huì)出現(xiàn)流控。
?流控模式-關(guān)聯(lián)(言簡(jiǎn)意賅:兩個(gè)服務(wù)共同參與限制條件原來是:A<C,現(xiàn)在是A+B<C)
1)說明:前面的兩種的流程模式都設(shè)置為直接,這種模式是默認(rèn)的,也就是說流量控制規(guī)則到達(dá)閾值時(shí)直接觸發(fā)流量控制。本小節(jié)說明關(guān)聯(lián)模式,均以QPS類型說明,后同。
2)關(guān)聯(lián):當(dāng)兩個(gè)資源之間具有資源爭(zhēng)搶或者依賴關(guān)系的時(shí)候,這兩個(gè)資源便具有了關(guān)聯(lián)。比如對(duì)數(shù)據(jù)庫同一個(gè)字段的讀操作和寫操作存在爭(zhēng)搶,讀的速度過高會(huì)影響寫得速度,寫的速度過高會(huì)影響讀的速度。如果放任讀寫操作爭(zhēng)搶資源,則爭(zhēng)搶本身帶來的開銷會(huì)降低整體的吞吐量。關(guān)聯(lián)的關(guān)系是反向關(guān)聯(lián)。
3)上述代碼中的/testA和/testB就是關(guān)聯(lián)關(guān)系,它們?cè)谕粋€(gè)controller中,占用相同的資源,編輯配置如下:
使用Jmeter對(duì)/testB發(fā)送超過閾值的并發(fā)請(qǐng)求,那么在發(fā)送的同時(shí)再訪問/testA就會(huì)出現(xiàn)流控。原因是兩個(gè)請(qǐng)求相互爭(zhēng)搶資源,進(jìn)行了流控。
流控模式-鏈路:
鏈路模式也就是對(duì)某一條鏈路進(jìn)行流控。如用戶服務(wù)會(huì)調(diào)用訂單服務(wù),商品服務(wù)也會(huì)調(diào)用訂單服務(wù),就存在兩條鏈路。在某個(gè)時(shí)刻,對(duì)商品服務(wù)->訂單服務(wù)這條鏈路進(jìn)行流控,從而保證訂單服務(wù)的正常使用,最終讓用戶服務(wù)可以正常調(diào)用訂單服務(wù),雖然限流了商品服務(wù)這條鏈路,但不影響用戶服務(wù)這條鏈路。
流控效果-快速失敗:
默認(rèn)的流量控制方式,當(dāng)QPS超過任意規(guī)則的閾值后,新的請(qǐng)求就會(huì)被立即拒絕,拒絕方式為拋出FlowException
。前面已經(jīng)使用過多次。
流控效果-Warm Up
預(yù)熱/冷啟動(dòng)方式。當(dāng)系統(tǒng)長(zhǎng)期處于低水位的情況下,當(dāng)流量突然增加時(shí),直接把系統(tǒng)拉升到高水位可能瞬間把系統(tǒng)壓垮。通過"冷啟動(dòng)",讓通過的流量緩慢增加,在一定時(shí)間內(nèi)逐漸增加到閾值上限,給冷系統(tǒng)一個(gè)預(yù)熱的時(shí)間,避免冷系統(tǒng)被壓垮。它有一個(gè)冷加載因子,值是3。曲線圖如下
新加/testA的流控規(guī)則如下:
當(dāng)1秒同時(shí)有20個(gè)請(qǐng)求,預(yù)熱時(shí)間是10秒。那么服務(wù)會(huì)先處理7個(gè)請(qǐng)求(20/3),后面依次處理,當(dāng)達(dá)到20秒時(shí)處理完所有的請(qǐng)求。
流控效果-排隊(duì)等待
讓請(qǐng)求以均勻的速度通過。修改/testA的規(guī)則
也就是說,當(dāng)有大量的請(qǐng)求來時(shí),每秒只處理20個(gè)請(qǐng)求,其他的請(qǐng)求進(jìn)行排隊(duì)等待,依次類推。當(dāng)后面排隊(duì)的時(shí)間超過5秒時(shí)就報(bào)錯(cuò),顯示流控信息。
熔斷降級(jí)
一個(gè)服務(wù)常常會(huì)調(diào)用別的模塊,如果依賴的服務(wù)出現(xiàn)了不穩(wěn)定的情況,請(qǐng)求的響應(yīng)時(shí)間變長(zhǎng),那么調(diào)用服務(wù)的方法的響應(yīng)時(shí)間也會(huì)變長(zhǎng),線程會(huì)產(chǎn)生堆積,最終可能耗盡業(yè)務(wù)自身的線程池,服務(wù)本身也變得不可用。而Sentinel在服務(wù)出現(xiàn)不穩(wěn)定情況時(shí),會(huì)對(duì)其進(jìn)行限制,請(qǐng)求快速失敗,避免影響到其他資源而導(dǎo)致級(jí)聯(lián)錯(cuò)誤。當(dāng)資源被降級(jí)后,在接下來的時(shí)間窗口內(nèi),對(duì)該資源的調(diào)用都自動(dòng)熔斷。
(1)慢調(diào)用比例:當(dāng)單位統(tǒng)計(jì)時(shí)長(zhǎng)內(nèi)請(qǐng)求數(shù)目大于設(shè)置的最小請(qǐng)求數(shù)目,并且平均響應(yīng)時(shí)間超過最大RT的請(qǐng)求的比例大于閾值,則接下來的熔斷時(shí)長(zhǎng)內(nèi)請(qǐng)求會(huì)自動(dòng)被熔斷。
經(jīng)過熔斷時(shí)長(zhǎng)后熔斷器會(huì)進(jìn)入探測(cè)恢復(fù)狀態(tài),若接下來的一個(gè)請(qǐng)求成功完成則結(jié)束熔斷,否則會(huì)再次被熔斷。
說明:在1000ms內(nèi)請(qǐng)求數(shù)超過5個(gè),且平均響應(yīng)時(shí)間超過300ms的請(qǐng)求的比例(超過300ms的請(qǐng)求占總請(qǐng)求的比例)大于0.4,則該資源自動(dòng)熔斷10s。10s后根據(jù)下一個(gè)請(qǐng)求判斷是否再次被熔斷。
(2)異常比例:當(dāng)單位統(tǒng)計(jì)時(shí)長(zhǎng)內(nèi)請(qǐng)求數(shù)目大于設(shè)置的最小請(qǐng)求數(shù)目,并且異常的比例大于閾值,則接下來的熔斷時(shí)長(zhǎng)內(nèi)請(qǐng)求會(huì)自動(dòng)被熔斷。
經(jīng)過熔斷時(shí)長(zhǎng)后熔斷器會(huì)進(jìn)入探測(cè)恢復(fù)狀態(tài),若接下來的一個(gè)請(qǐng)求成功完成則結(jié)束熔斷,否則會(huì)再次被熔斷。
說明:在1000ms內(nèi)請(qǐng)求數(shù)超過5個(gè),且異常的請(qǐng)求超過6個(gè),那么該資源將自動(dòng)熔斷20s。20s后根據(jù)下一個(gè)請(qǐng)求判斷是否再次被熔斷。
@SentinelResource的使用
前面的所講的流控或降級(jí),其返回的數(shù)據(jù)都是?Blocked by Sentinel (flow limiting) ,當(dāng)然可以自定義。@SentinelResource和@HystrixCommand的作用是類似的,都是來指定流控或降級(jí)時(shí)返回的信息。
在方法上加@SentinelResource注解,且使用blockHandler(或者blockHandlerClass)指定流控或降級(jí)時(shí)的自定義提示,而blockHandler函數(shù)訪問范圍需要是public,返回類型需要與原方法相匹配,參數(shù)類型需要和原方法相匹配并且最后加一個(gè)額外的參數(shù)(類型是BlockException),且和原方法在同一個(gè)類中。使用fallback 指定未流控或降級(jí)發(fā)生異常時(shí)的自定義提示,其方法必須是public,返回類型需要與原方法相匹配,參數(shù)類型需要和原方法相匹配。
下面通過對(duì)/testC進(jìn)行流控和降級(jí)來說明:
1)流控配置:
2)降級(jí)配置:
修改controller
package com.lgc.cloudalibabasentinel.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 org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FlowLimitController{
@GetMapping("/testA")
public String testA(){
return "--------testA";
}
@GetMapping("/testB")
public String testB(){
return "--------testB";
}
@GetMapping("/testC")
@SentinelResource(value = "aaa",blockHandler = "testCBlockHandler",fallback = "testCFallback")
public String testC(Integer id){
if (id < 0) {
throw new RuntimeException("參數(shù)值格式錯(cuò)誤");
}
return "--------testC";
}
//自定義降級(jí)或熔斷時(shí)的提示信息
public String testCBlockHandler(Integer id, BlockException exception){
//判斷異常的類型
if (exception instanceof FlowException){
return "你被限流了,請(qǐng)稍后再試";
} else if (exception instanceof DegradeException) {
return "你被降級(jí)了,請(qǐng)稍后再試";
}
return "當(dāng)前服務(wù)不可用";
}
//自定義未限流時(shí)發(fā)生 異常 的提示信息
public String testCFallback(Integer id){
return "參數(shù)不合法";
}
}
在@SentinelResource指定了value,其值就是要流控或降級(jí)的資源名,必須配置。
當(dāng)訪問/testC?id=8時(shí),快速刷新,會(huì)出現(xiàn)流控提示信息。
當(dāng)問/testC?id=-5時(shí),刷新1此,會(huì)出現(xiàn)錯(cuò)誤提示信息。
當(dāng)問/testC?id=-5時(shí),刷新5次以上,會(huì)出現(xiàn)降級(jí)提示信息。
規(guī)則持久化
每次無論重啟sentinel服務(wù)還是要監(jiān)控的服務(wù),sentinel頁面的配置規(guī)則都會(huì)消失,這是因?yàn)檫@些規(guī)則沒有持久化,對(duì)應(yīng)大量的配置規(guī)則,持久化也非常重要,可將其配置到nacos中。
這里直接在cloud-alibaba-sentinel模塊進(jìn)行說明:
1)導(dǎo)入依賴:
<!--springcloud alibaba sentinel-datasource-nacos-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2)在yml配置,已存在配置省略:
spring:
cloud:
# 流控規(guī)則持久化到nacos
datasource:
dsl:
nacos:
server-addr: ${spring.cloud.nacos.server-addr}
data-id: ${spring.application.name}
group-id: DEFAULT_GROUP
data-type: json
rule-type: flow
3)在nacos中添加配置文件,如下圖:
json內(nèi)容:文章來源:http://www.zghlxwxcb.cn/news/detail-740397.html
[
{
"resource": "/testA",
"limitApp": "default",
"grade": 1,
"count": 5,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
可看到j(luò)son中是一個(gè)數(shù)組,數(shù)組中只有一個(gè)元素,那么針對(duì)/test的請(qǐng)求的配置規(guī)則會(huì)存下來,不會(huì)因?yàn)橹貑⒍鴣G失,而其他的請(qǐng)求的配置規(guī)則還是丟失。針對(duì)這些請(qǐng)求,都按照這種規(guī)則配置在數(shù)組中即可。文章來源地址http://www.zghlxwxcb.cn/news/detail-740397.html
到了這里,關(guān)于SpringCloud Alibaba Demo(Nacos,OpenFeign,Gatway,Sentinel)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!