From 07e7e978dc20c58bebb00d05a0d943509edc3160 Mon Sep 17 00:00:00 2001
From: qyx <565485304@qq.com>
Date: Sun, 29 Sep 2024 15:42:24 +0800
Subject: [PATCH] =?UTF-8?q?feat(master):sentinel=20=E7=9B=B8=E5=85=B3?=
=?UTF-8?q?=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
代码完成
---
.../SpringCloud项目介绍.md | 3 +-
.../README.md | 3 +
.../dev-protocol-springcloud-sentinel/pom.xml | 76 +++++++++++++++++
.../example/SentinelClientApplication.java | 18 +++++
.../example/block_handler/QBlockHandler.java | 29 +++++++
.../conf/RestTemplateExceptionUtil.java | 44 ++++++++++
.../java/org/example/conf/SentinelConfig.java | 26 ++++++
.../controller/FlowRuleCodeController.java | 81 +++++++++++++++++++
.../controller/RateLimitController.java | 43 ++++++++++
.../SentinelFallbackController.java | 72 +++++++++++++++++
.../controller/SentinelFeignController.java | 33 ++++++++
.../SentinelRestTemplateController.java | 53 ++++++++++++
.../fallback_handler/QFallbackHandler.java | 33 ++++++++
.../example/feign/SentinelFeignClient.java | 20 +++++
.../feign/SentinelFeignClientFallback.java | 22 +++++
.../src/main/resources/bootstrap.yml | 59 ++++++++++++++
.../main/resources/http/flow-rule-code.http | 3 +
.../src/main/resources/http/rate-limit.http | 7 ++
.../resources/http/sentinel-fallback.http | 12 +++
.../resources/http/sentinel-feign-client.http | 3 +
.../http/sentinel-rest-template.http | 8 ++
pom.xml | 1 +
22 files changed, 648 insertions(+), 1 deletion(-)
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/README.md
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/pom.xml
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/SentinelClientApplication.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/block_handler/QBlockHandler.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/RestTemplateExceptionUtil.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/SentinelConfig.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/FlowRuleCodeController.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/RateLimitController.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFallbackController.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFeignController.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelRestTemplateController.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/fallback_handler/QFallbackHandler.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClient.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClientFallback.java
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/bootstrap.yml
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/flow-rule-code.http
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/rate-limit.http
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-fallback.http
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-feign-client.http
create mode 100644 dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-rest-template.http
diff --git a/dev-protocol-springcloud/SpringCloud项目介绍.md b/dev-protocol-springcloud/SpringCloud项目介绍.md
index c31245c..434697f 100644
--- a/dev-protocol-springcloud/SpringCloud项目介绍.md
+++ b/dev-protocol-springcloud/SpringCloud项目介绍.md
@@ -37,4 +37,5 @@
- [dev-protocol-springcloud-project-goods-service](dev-protocol-springcloud-project-goods-service)
- 订单微服务
- [dev-protocol-springcloud-project-order-service](dev-protocol-springcloud-project-order-service)
-- 物流微服务
\ No newline at end of file
+- 物流微服务
+ - [dev-protocol-springcloud-project-logistics-service](dev-protocol-springcloud-project-logistics-service)
\ No newline at end of file
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/README.md b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/README.md
new file mode 100644
index 0000000..3f6cfc7
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/README.md
@@ -0,0 +1,3 @@
+# sentinel
+
+
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/pom.xml b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/pom.xml
new file mode 100644
index 0000000..fc23223
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/pom.xml
@@ -0,0 +1,76 @@
+
+
+ 4.0.0
+
+ org.example
+ dev-protocol
+ 1.0-SNAPSHOT
+ ../../pom.xml
+
+
+ dev-protocol-springcloud-sentinel
+ 1.0-SNAPSHOT
+ jar
+
+
+ dev-protocol-springcloud-sentinel
+ Sentinel Client
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-sentinel
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+ com.alibaba.csp
+ sentinel-datasource-nacos
+
+
+
+ org.example
+ dev-protocol-springcloud-project-mvc-config
+ 1.0-SNAPSHOT
+
+
+
+
+
+ ${artifactId}
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ repackage
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/SentinelClientApplication.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/SentinelClientApplication.java
new file mode 100644
index 0000000..93ad36a
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/SentinelClientApplication.java
@@ -0,0 +1,18 @@
+package org.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+/**
+ *
Sentinel 集成到 SpringCloud 工程中
+ * */
+@EnableFeignClients
+@EnableDiscoveryClient
+@SpringBootApplication
+public class SentinelClientApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(SentinelClientApplication.class, args);
+ }
+}
\ No newline at end of file
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/block_handler/QBlockHandler.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/block_handler/QBlockHandler.java
new file mode 100644
index 0000000..f9af17c
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/block_handler/QBlockHandler.java
@@ -0,0 +1,29 @@
+package org.example.block_handler;
+
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.alibaba.fastjson2.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.example.vo.CommonResponse;
+
+/**
+ * 自定义通用的限流处理逻辑
+ * */
+@Slf4j
+public class QBlockHandler {
+
+
+ /**
+ * 通用限流处理方法
+ * 这个方法必须是 static 的
+ * */
+ public static CommonResponse qHandleBlockException(BlockException exception) {
+
+ log.error("trigger q block handler: [{}], [{}]",
+ JSON.toJSONString(exception.getRule()), exception.getRuleLimitApp());
+ return new CommonResponse<>(
+ -1,
+ "flow rule trigger block exception",
+ null
+ );
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/RestTemplateExceptionUtil.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/RestTemplateExceptionUtil.java
new file mode 100644
index 0000000..d05bcde
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/RestTemplateExceptionUtil.java
@@ -0,0 +1,44 @@
+package org.example.conf;
+
+import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.example.vo.JwtToken;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+
+/**
+ * RestTemplate 在限流或异常时的兜底方法
+ * */
+@Slf4j
+public class RestTemplateExceptionUtil {
+
+ /**
+ * 限流后的处理方法
+ * */
+ public static SentinelClientHttpResponse handleBlock(HttpRequest request,
+ byte[] body,
+ ClientHttpRequestExecution execution,
+ BlockException ex) {
+ log.error("Handle RestTemplate Block Exception: [{}], [{}]",
+ request.getURI().getPath(), ex.getClass().getCanonicalName());
+ return new SentinelClientHttpResponse(
+ JSON.toJSONString(new JwtToken("q-block"))
+ );
+ }
+
+ /**
+ * 异常降级之后的处理方法
+ * */
+ public static SentinelClientHttpResponse handleFallback(HttpRequest request,
+ byte[] body,
+ ClientHttpRequestExecution execution,
+ BlockException ex) {
+ log.error("Handle RestTemplate Fallback Exception: [{}], [{}]",
+ request.getURI().getPath(), ex.getClass().getCanonicalName());
+ return new SentinelClientHttpResponse(
+ JSON.toJSONString(new JwtToken("q-block"))
+ );
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/SentinelConfig.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/SentinelConfig.java
new file mode 100644
index 0000000..26e5ae8
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/conf/SentinelConfig.java
@@ -0,0 +1,26 @@
+package org.example.conf;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * 开启服务间的调用保护, 需要给 RestTemplate 做一些包装
+ * */
+@Slf4j
+@Configuration
+public class SentinelConfig {
+
+ /**
+ * 包装 RestTemplate
+ * */
+ @Bean
+// @SentinelRestTemplate(
+// fallback = "handleFallback", fallbackClass = RestTemplateExceptionUtil.class,
+// blockHandler = "handleBlock", blockHandlerClass = RestTemplateExceptionUtil.class
+// )
+ public RestTemplate restTemplate() {
+ return new RestTemplate(); // 可以对其做一些业务相关的配置
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/FlowRuleCodeController.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/FlowRuleCodeController.java
new file mode 100644
index 0000000..98e1521
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/FlowRuleCodeController.java
@@ -0,0 +1,81 @@
+package org.example.controller;
+
+import com.alibaba.csp.sentinel.annotation.SentinelResource;
+import com.alibaba.csp.sentinel.slots.block.BlockException;
+import com.alibaba.csp.sentinel.slots.block.RuleConstant;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
+import com.alibaba.fastjson2.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.example.block_handler.QBlockHandler;
+import org.example.vo.CommonResponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 流控规则硬编码的 Controller
+ * */
+@Slf4j
+@RestController
+@RequestMapping("/code")
+public class FlowRuleCodeController {
+
+ /**
+ * 初始化流控规则
+ * */
+ @PostConstruct
+ public void init() {
+
+ // 流控规则集合
+ List flowRules = new ArrayList<>();
+ // 创建流控规则
+ FlowRule flowRule = new FlowRule();
+ // 设置流控规则 QPS, 限流阈值类型 (QPS, 并发线程数)
+ flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
+ // 流量控制手段
+ flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
+ // 设置受保护的资源
+ flowRule.setResource("flowRuleCode");
+ // 设置受保护的资源的阈值
+ flowRule.setCount(1);
+ flowRules.add(flowRule);
+
+ // 加载配置好的规则
+ FlowRuleManager.loadRules(flowRules);
+ }
+
+ /**
+ * 采用硬编码限流规则的 Controller 方法
+ * */
+ @GetMapping("/flow-rule")
+// @SentinelResource(value = "flowRuleCode")
+// @SentinelResource(value = "flowRuleCode", blockHandler = "handleException")
+ @SentinelResource(
+ value = "flowRuleCode", blockHandler = "qHandleBlockException",
+ blockHandlerClass = QBlockHandler.class
+ )
+ public CommonResponse flowRuleCode() {
+ log.info("request flowRuleCode");
+ return new CommonResponse<>(0, "", "q-ecommerce");
+ }
+
+ /**
+ * 当限流异常抛出时, 指定调用的方法
+ * 是一个兜底策略, 必须和上面使用的方法在一个类中
+ * */
+ public CommonResponse handleException(BlockException exception) {
+ log.error("has block exception: [{}]", JSON.toJSONString(exception.getRule()));
+ return new CommonResponse<>(
+ -1,
+ "flow rule exception",
+ exception.getClass().getCanonicalName()
+ );
+ }
+
+
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/RateLimitController.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/RateLimitController.java
new file mode 100644
index 0000000..283de8c
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/RateLimitController.java
@@ -0,0 +1,43 @@
+package org.example.controller;
+
+import com.alibaba.csp.sentinel.annotation.SentinelResource;
+import lombok.extern.slf4j.Slf4j;
+import org.example.block_handler.QBlockHandler;
+import org.example.vo.CommonResponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 基于 Sentinel 控制台配置流控规则
+ * Sentinel 是懒加载的, 先去访问一下, 就可以在 Sentinel Dashboard 看到了
+ * */
+@Slf4j
+@RestController
+@RequestMapping("/dashboard")
+public class RateLimitController {
+
+ /**
+ * 在 dashboard 中 "流控规则" 中按照资源名称新增流控规则
+ * */
+ @GetMapping("/by-resource")
+ @SentinelResource(
+ value = "byResource",
+ blockHandler = "qHandleBlockException",
+ blockHandlerClass = QBlockHandler.class
+ )
+ public CommonResponse byResource() {
+ log.info("coming in rate limit controller by resource");
+ return new CommonResponse<>(0, "", "byResource");
+ }
+
+ /**
+ * 在 "簇点链路" 中给 url 添加流控规则
+ * */
+ @GetMapping("/by-url")
+ @SentinelResource(value = "byUrl")
+ public CommonResponse byUrl() {
+ log.info("coming in rate limit controller by url");
+ return new CommonResponse<>(0, "", "byUrl");
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFallbackController.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFallbackController.java
new file mode 100644
index 0000000..b64b1c7
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFallbackController.java
@@ -0,0 +1,72 @@
+package org.example.controller;
+
+import com.alibaba.csp.sentinel.annotation.SentinelResource;
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.example.fallback_handler.QFallbackHandler;
+import org.example.vo.JwtToken;
+import org.example.vo.UsernameAndPassword;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Sentinel 提供容错降级的功能
+ * */
+@SuppressWarnings("all")
+@Slf4j
+@RestController
+@RequestMapping("/sentinel-fallback")
+public class SentinelFallbackController {
+
+ /** 注入没有增强的 RestTemplate */
+ private final RestTemplate restTemplate;
+
+ public SentinelFallbackController(RestTemplate restTemplate) {
+ this.restTemplate = restTemplate;
+ }
+
+ @PostMapping("/get-token")
+ @SentinelResource(
+ value = "getTokenFromAuthorityService",
+ fallback = "getTokenFromAuthorityServiceFallback",
+ fallbackClass = { QFallbackHandler.class }
+ )
+ public JwtToken getTokenFromAuthorityService(
+ @RequestBody UsernameAndPassword usernameAndPassword) {
+
+ String requestUrl =
+ "http://127.0.0.1:7000/dev-protocol-springcloud-project-authority-center/authority/token";
+ log.info("RestTemplate request url and body: [{}], [{}]",
+ requestUrl, JSON.toJSONString(usernameAndPassword));
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ return restTemplate.postForObject(
+ requestUrl,
+ new HttpEntity<>(JSON.toJSONString(usernameAndPassword), headers),
+ JwtToken.class
+ );
+ }
+
+ /**
+ * 让 Sentinel 忽略一些异常
+ * */
+ @GetMapping("/ignore-exception")
+ @SentinelResource(
+ value = "ignoreException",
+ fallback = "ignoreExceptionFallback",
+ fallbackClass = { QFallbackHandler.class },
+ exceptionsToIgnore = { NullPointerException.class }
+ )
+ public JwtToken ignoreException(@RequestParam Integer code) {
+
+ if (code % 2 == 0) {
+ throw new NullPointerException("yout input code is: " + code);
+ }
+
+ return new JwtToken("qinyi-imooc");
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFeignController.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFeignController.java
new file mode 100644
index 0000000..2f805c4
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelFeignController.java
@@ -0,0 +1,33 @@
+package org.example.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.example.feign.SentinelFeignClient;
+import org.example.vo.CommonResponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * OpenFeign 集成 Sentinel 实现熔断降级
+ * */
+@Slf4j
+@RestController
+@RequestMapping("/sentinel-feign")
+public class SentinelFeignController {
+
+ private final SentinelFeignClient sentinelFeignClient;
+
+ public SentinelFeignController(SentinelFeignClient sentinelFeignClient) {
+ this.sentinelFeignClient = sentinelFeignClient;
+ }
+
+ /**
+ * 通过 Feign 接口去获取结果
+ * */
+ @GetMapping("/result-by-feign")
+ public CommonResponse getResultByFeign(@RequestParam Integer code) {
+ log.info("coming in get result by feign: [{}]", code);
+ return sentinelFeignClient.getResultByFeign(code);
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelRestTemplateController.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelRestTemplateController.java
new file mode 100644
index 0000000..2d58b3a
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/controller/SentinelRestTemplateController.java
@@ -0,0 +1,53 @@
+package org.example.controller;
+
+import com.alibaba.fastjson.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.example.vo.JwtToken;
+import org.example.vo.UsernameAndPassword;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * 使用 Sentinel 保护 RestTemplate 服务间调用
+ * */
+@Slf4j
+@RestController
+@RequestMapping("/sentinel-rest-template")
+public class SentinelRestTemplateController {
+
+ private final RestTemplate restTemplate;
+
+ public SentinelRestTemplateController(RestTemplate restTemplate) {
+ this.restTemplate = restTemplate;
+ }
+
+ /**
+ * 从授权服务中获取 JwtToken
+ * 1. 流控降级:
+ * 是针对于簇点链路中的 http://127.0.0.1:7000/ecommerce-authority-center/authority/token
+ * 2. 容错降级: 对于服务不可用时不能生效
+ * */
+ @PostMapping("/get-token")
+ public JwtToken getTokenFromAuthorityService(
+ @RequestBody UsernameAndPassword usernameAndPassword) {
+
+ String requestUrl =
+ "http://127.0.0.1:7000/dev-protocol-springcloud-project-authority-center/authority/token";
+ log.info("RestTemplate request url and body: [{}], [{}]",
+ requestUrl, JSON.toJSONString(usernameAndPassword));
+
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ return restTemplate.postForObject(
+ requestUrl,
+ new HttpEntity<>(JSON.toJSONString(usernameAndPassword), headers),
+ JwtToken.class
+ );
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/fallback_handler/QFallbackHandler.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/fallback_handler/QFallbackHandler.java
new file mode 100644
index 0000000..f019816
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/fallback_handler/QFallbackHandler.java
@@ -0,0 +1,33 @@
+package org.example.fallback_handler;
+
+import com.alibaba.fastjson2.JSON;
+import lombok.extern.slf4j.Slf4j;
+import org.example.vo.JwtToken;
+import org.example.vo.UsernameAndPassword;
+
+/**
+ * Sentinel 回退降级的兜底策略
+ * 都需要是静态方法
+ * */
+@Slf4j
+public class QFallbackHandler {
+
+ /**
+ * getTokenFromAuthorityService 方法的 fallback
+ * */
+ public static JwtToken getTokenFromAuthorityServiceFallback(
+ UsernameAndPassword usernameAndPassword
+ ) {
+ log.error("get token from authority service fallback: [{}]",
+ JSON.toJSONString(usernameAndPassword));
+ return new JwtToken("q-fallback");
+ }
+
+ /**
+ * ignoreException 方法的 fallback
+ * */
+ public static JwtToken ignoreExceptionFallback(Integer code) {
+ log.error("ignore exception input code: [{}] has trigger exception", code);
+ return new JwtToken("q-fallback");
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClient.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClient.java
new file mode 100644
index 0000000..ecbae1b
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClient.java
@@ -0,0 +1,20 @@
+package org.example.feign;
+
+import org.example.vo.CommonResponse;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * 通过 Sentinel 对 OpenFeign 实现熔断降级
+ * */
+@FeignClient(
+ value = "dev-protocol-springcloud-sentinel-null", // 定义不存在的服务名称, 测试是否正常执行
+ fallback = SentinelFeignClientFallback.class
+)
+public interface SentinelFeignClient {
+
+ @RequestMapping(value = "qinyi", method = RequestMethod.GET)
+ CommonResponse getResultByFeign(@RequestParam Integer code);
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClientFallback.java b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClientFallback.java
new file mode 100644
index 0000000..7e394d9
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/java/org/example/feign/SentinelFeignClientFallback.java
@@ -0,0 +1,22 @@
+package org.example.feign;
+
+import lombok.extern.slf4j.Slf4j;
+import org.example.vo.CommonResponse;
+import org.springframework.stereotype.Component;
+
+/**
+ * Sentinel 对 OpenFeign 接口的降级策略
+ * */
+@Slf4j
+@Component
+public class SentinelFeignClientFallback implements SentinelFeignClient{
+ @Override
+ public CommonResponse getResultByFeign(Integer code) {
+ log.error("request supply for test has some error: [{}]", code);
+ return new CommonResponse<>(
+ -1,
+ "sentinel feign fallback",
+ "input code: "+ code
+ );
+ }
+}
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/bootstrap.yml b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..2d6028c
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/bootstrap.yml
@@ -0,0 +1,59 @@
+server:
+ port: 8100
+ servlet:
+ context-path: /dev-protocol-springcloud-sentinel
+
+spring:
+ application:
+ name: dev-protocol-springcloud-sentinel # 应用名称也是构成 Nacos 配置管理 dataId 字段的一部分 (当 config.prefix 为空时)
+ cloud:
+ nacos:
+ # 服务注册发现
+ discovery:
+ enabled: true # 如果不想使用 Nacos 进行服务注册和发现, 设置为 false 即可
+ server-addr: 127.0.0.1:8848
+ # server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850 # Nacos 服务器地址
+ namespace: 1ccc74ae-9398-4dbe-b9d7-4f9addf9f40c
+ metadata:
+ management:
+ context-path: ${server.servlet.context-path}/actuator
+ sentinel:
+ # 配置 sentinel dashboard 地址
+ transport:
+ dashboard: 127.0.0.1:7777
+ port: 8719 # 会在应用对应的机器上启动一个 Http Server, 该 Server 会与 Sentinel 控制台做交互
+ datasource:
+ # 名称任意, 代表数据源
+ ds:
+ nacos:
+ # NacosDataSourceProperties.java 中定义
+ server-addr: ${spring.cloud.nacos.discovery.server-addr}
+ dataId: ${spring.application.name}-sentinel
+ namespace: ${spring.cloud.nacos.discovery.namespace}
+ groupId: DEFAULT_GROUP
+ data-type: json
+ # 规则类型: com.alibaba.cloud.sentinel.datasource.RuleType
+ # FlowRule 就是限流规则
+ rule-type: flow
+ # 服务启动直接建立心跳连接
+ eager: true
+
+# 暴露端点
+management:
+ endpoints:
+ web:
+ exposure:
+ include: '*'
+ endpoint:
+ health:
+ show-details: always
+
+# 打开 Sentinel 对 Feign 的支持
+feign:
+ sentinel:
+ enabled: true
+
+# 开启或关闭 @SentinelRestTemplate 注解
+resttemplate:
+ sentinel:
+ enabled: true
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/flow-rule-code.http b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/flow-rule-code.http
new file mode 100644
index 0000000..7c02a6d
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/flow-rule-code.http
@@ -0,0 +1,3 @@
+### 硬编码的流控规则
+GET 127.0.0.1:8100/dev-protocol-springcloud-sentinel/code/flow-rule
+Content-Type: application/json
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/rate-limit.http b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/rate-limit.http
new file mode 100644
index 0000000..e7ccbe4
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/rate-limit.http
@@ -0,0 +1,7 @@
+### 根据资源名称限流
+GET 127.0.0.1:8100/dev-protocol-springcloud-sentinel/dashboard/by-resource
+Content-Type: application/json
+
+### 根据 URL 限流
+GET 127.0.0.1:8100/dev-protocol-springcloud-sentinel/dashboard/by-url
+Content-Type: application/json
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-fallback.http b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-fallback.http
new file mode 100644
index 0000000..76cd68d
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-fallback.http
@@ -0,0 +1,12 @@
+### 获取 token
+POST 127.0.0.1:8100/dev-protocol-springcloud-sentinel/sentinel-fallback/get-token
+Content-Type: application/json
+
+{
+ "username": "1@qqq.com",
+ "password": "25d55ad283aa400af464c76d713c07ad"
+}
+
+### 忽略异常
+GET 127.0.0.1:8100/dev-protocol-springcloud-sentinel/sentinel-fallback/ignore-exception?code=2
+Content-Type: application/json
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-feign-client.http b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-feign-client.http
new file mode 100644
index 0000000..67fd1f3
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-feign-client.http
@@ -0,0 +1,3 @@
+### Sentinel Feign Client
+GET 127.0.0.1:8100/dev-protocol-springcloud-sentinel/sentinel-feign/result-by-feign?code=200
+Content-Type: application/json
diff --git a/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-rest-template.http b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-rest-template.http
new file mode 100644
index 0000000..1f4620b
--- /dev/null
+++ b/dev-protocol-springcloud/dev-protocol-springcloud-sentinel/src/main/resources/http/sentinel-rest-template.http
@@ -0,0 +1,8 @@
+### 获取 Token
+POST 127.0.0.1:8100/dev-protocol-springcloud-sentinel/sentinel-rest-template/get-token
+Content-Type: application/json
+
+{
+ "username": "1@qqq.com",
+ "password": "25d55ad283aa400af464c76d713c07ad"
+}
diff --git a/pom.xml b/pom.xml
index bc97e08..417463d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,7 @@
dev-protocol-springcloud/dev-protocol-springcloud-message-study
dev-protocol-springcloud/dev-protocol-springcloud-project-order-service
dev-protocol-springcloud/dev-protocol-springcloud-project-logistics-service
+ dev-protocol-springcloud/dev-protocol-springcloud-sentinel