提交 3dc2f246 编写于 作者: Afeiamic's avatar Afeiamic 🤺

Merge branch 'feature-dev-230126' into 'master'

Feature dev 230126

See merge request Afeiamix/SpringCloud!19
<?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</artifactId>
<groupId>com.afeiamic.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-consumer-nacos-order84</artifactId>
<dependencies>
<!-- 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>
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 引入自己定义的 api 通用包,可以使用 Payment 支付 Entity -->
<dependency>
<groupId>org.afeiamic.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot 整合 Web 组件 -->
<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>
<!-- 日常通用 jar 包配置 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.afeiamic.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderNacosMain84 {
public static void main(String[] args) {
SpringApplication.run(OrderNacosMain84.class, args);
}
}
package com.afeiamic.springcloud.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
package com.afeiamic.springcloud.controller;
import com.afeiamic.springcloud.entities.Payment;
import com.afeiamic.springcloud.entities.R;
import com.afeiamic.springcloud.service.PaymentService;
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.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
public class CircleBreakerController {
private static final String SERVER_URL = "http://nacos-payment-provider";
@Resource
private RestTemplate restTemplate;
@SuppressWarnings({"unchecked"})
@GetMapping("/consumer/fallback/{id}")
// @SentinelResource(value = "fallback", fallback = "handleFallback") // fallback 负责处理业务异常
// @SentinelResource(value = "fallback", blockHandler = "blockHandler") // blockHandler 负责在 sentinel 里面配置的降级限流
@SentinelResource(value = "fallback", blockHandler = "blockHandler", fallback = "handleFallback",
exceptionsToIgnore = IllegalArgumentException.class) // 加入报该异常不再有 fallback 兜底, 没有降级效果
public R<Payment> fallback(@PathVariable Long id) {
R<Payment> result = restTemplate.getForObject(SERVER_URL + "/paymentSQL/" + id, R.class);
if (id == 4) {
throw new IllegalArgumentException("IllegalArgumentException, 非法参数异常!");
} else {
assert result != null;
if (result.getData() == null) {
throw new NullPointerException("NullPointerException, 该ID没有对应记录,空指针异常");
}
}
return result;
}
public R<Payment> handleFallback(@PathVariable Long id, Throwable e) {
Payment payment = new Payment(id, null);
return new R<>(444, "兜底异常 handleFallback,exception 内容" + e.getMessage(), payment);
}
public R<Payment> blockHandler(@PathVariable Long id, BlockException e) {
Payment payment = new Payment(id, null);
return new R<>(445, "blockHandler-sentinel 限流 , 无此流水 : blockException" + e.getMessage(), payment);
}
//==================OpenFeign
@Resource
private PaymentService paymentService;
@GetMapping("/consumer/paymentSQL/{id}")
public R<Payment> paymentSQL(@PathVariable Long id) {
if (id == 4) {
throw new RuntimeException("没有该id");
}
return paymentService.paymentSQL(id);
}
}
package com.afeiamic.springcloud.service;
import com.afeiamic.springcloud.entities.Payment;
import com.afeiamic.springcloud.entities.R;
import com.afeiamic.springcloud.service.fallback.PaymentFallbackService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* 使用 fallback 方式是无法获取异常信息的,
* 如果想要获取异常信息,可以使用 fallbackFactory 参数
*/
@FeignClient(value = "nacos-payment-provider", fallback = PaymentFallbackService.class) // 调用过程中关闭9003服务者
public interface PaymentService {
@GetMapping(value = "/paymentSQL/{id}")
public R<Payment> paymentSQL(@PathVariable("id") Long id);
}
package com.afeiamic.springcloud.service.fallback;
import com.afeiamic.springcloud.entities.Payment;
import com.afeiamic.springcloud.entities.R;
import com.afeiamic.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
@Service
public class PaymentFallbackService implements PaymentService {
@Override
public R<Payment> paymentSQL(Long id) {
return new R<>(444, "服务降级返回 , 没有该流水信息", new Payment(id, "errorSerial..."));
}
}
server:
port: 84
spring:
application:
name: nacos-order-consumer
cloud:
nacos:
discovery:
server-addr: http://localhost:8848
sentinel:
transport:
# 配置 Sentinel dashboard 地址
dashboard: localhost:8080
# 默认 8719 端口,假如被占用会自动从 8719 开始依次 +1 扫描 , 直至找到未被占用的端口
port: 8719
# 消费者将要去访问的微服务名称 ( 注册成功进 nacos 的微服务提供者 )
service-url:
nacos-user-service: http://nacos-payment-provider
# 激活sentinel对feign的支持
feign:
sentinel:
enabled: true
<?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</artifactId>
<groupId>com.afeiamic.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-provider-payment9003</artifactId>
<dependencies>
<!--SpringCloud Alibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
<groupId>org.afeiamic.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- SpringBoot整合Web组件 -->
<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>
<!--日常通用jar包配置-->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.afeiamic.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain9003 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain9003.class, args);
}
}
package com.afeiamic.springcloud.controller;
import com.afeiamic.springcloud.entities.Payment;
import com.afeiamic.springcloud.entities.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
public class PaymentController {
@Value("${server.port}")
private String serverPort;
public static HashMap<Long, Payment> hashMap = new HashMap<>();
static {
hashMap.put(1L, new Payment(1L, "28a8c1e3bc2742d8848569891fb42181"));
hashMap.put(2L, new Payment(2L, "bba8c1e3bc2742d8848569891ac32182"));
hashMap.put(3L, new Payment(3L, "6ua8c1e3bc2742d8848569891xt92183"));
}
@GetMapping(value = "/paymentSQL/{id}")
public R<Payment> paymentSQL(@PathVariable("id") Long id) {
Payment payment = hashMap.get(id);
return new R<>(200, "from mysql, server.port" + serverPort, payment);
}
}
server:
port: 9003
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 # 配置Nacos地址
management:
endpoints:
web:
exposure:
include: '*'
\ No newline at end of file
<?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</artifactId>
<groupId>com.afeiamic.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloudalibaba-sentinel-service8401</artifactId>
<dependencies>
<dependency> <!-- 引入自定义的API通用包, 可以使用 Payment 支付 Entity -->
<groupId>com.afeiamic.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba sentinel-datasource-nacos 后续做持久化用到 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!-- SpringCloud Alibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel</artifactId>
</dependency>
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- web -->
<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>
<!-- 一般基础通用配置 -->
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.afeiamic.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelTestMain8401 {
public static void main(String[] args) {
SpringApplication.run(SentinelTestMain8401.class, args);
}
}
package com.afeiamic.springcloud.config;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterContextConfig {
/**
* 在spring-cloud-alibaba v2.1.1.RELEASE及前,sentinel1.7.0及后,关闭URL PATH聚合需要通过该方式,spring-cloud-alibaba v2.1.1.RELEASE后,可以通过配置关闭:spring.cloud.sentinel.web-context-unify=false
* 手动注入Sentinel的过滤器,关闭Sentinel注入CommonFilter实例,修改配置文件中的 spring.cloud.sentinel.filter.enabled=false
* 入口资源聚合问题:https://github.com/alibaba/Sentinel/issues/1024 或 https://github.com/alibaba/Sentinel/issues/1213
* 入口资源聚合问题解决:https://github.com/alibaba/Sentinel/pull/1111
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new CommonFilter());
registrationBean.addUrlPatterns("/*");
// 入口资源关闭聚合
registrationBean.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
registrationBean.setName("sentinelFilter");
registrationBean.setOrder(1);
return registrationBean;
}
}
package com.afeiamic.springcloud.controller;
import com.afeiamic.springcloud.entities.Payment;
import com.afeiamic.springcloud.entities.R;
import com.afeiamic.springcloud.myhandler.CustomerBlockHandler;
import com.afeiamic.springcloud.service.FlowLimitService;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@RestController
@Slf4j
public class FlowLimitController {
@Resource
private FlowLimitService flowLimitService;
@GetMapping(value = "/testA")
public String testA() {
return "------testA";
}
@GetMapping(value = "/testB")
public String testB() {
return "------testB";
}
@GetMapping(value = "/testC")
public String testC() {
return flowLimitService.name() + "from testC";
}
@GetMapping(value = "/testD")
public String testD() {
return flowLimitService.name() + "from testD";
}
@GetMapping(value = "/testE")
public String testE() {
// 暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
log.info("=======> testE 测试 RT <=======");
return "-------testE";
}
@GetMapping(value = "/testF")
public String testF() {
log.info("testF 测试异常比例数");
int age = 10 / 0;
return "------testF";
}
@GetMapping(value = "/testG")
public String testG() {
log.info("testG 测试异常数");
int age = 10 / 0;
return "------testG";
}
@GetMapping("/testHotKey")
@SentinelResource(value = "hotKey", blockHandler = "hotKeyHandler")
public String testHotKey(
@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2) {
return "hotKey";
}
public static String hotKeyHandler(@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2, BlockException e) {
return "hostKey request faster";
}
@GetMapping(value = "byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException")
public R<Payment> byResource() {
return new R<>(200, "按资源名称限流测试 OK", new Payment(2023L, "serial001"));
}
public R<Payment> handleException(BlockException exception) {
return new R<>(444, exception.getClass().getCanonicalName() + "\t服务不可用");
}
@GetMapping( value = "/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public R<Payment> retaLimit() {
return new R<>(200, "/rateLimit/byUrl successful!", new Payment(2023L, "serial002"));
}
/**
* 自定义通用的限流处理逻辑
*
* blockHandlerClass = CustomerBlockHandler.class
* blockHandler = handleException2
* 上述配置:找 CustomerBlockHandler 类里的 handleException2 方法进行兜底处理
*/
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler", blockHandlerClass = CustomerBlockHandler.class, blockHandler = "handleException")
public R<Payment> customerBlockHandler() {
return new R<>(200, " 按客户自定义限流处理逻辑 ");
}
}
package com.afeiamic.springcloud.myhandler;
import com.afeiamic.springcloud.entities.R;
import com.alibaba.csp.sentinel.slots.block.BlockException;
public class CustomerBlockHandler {
public static R<String> handleException(BlockException exception) {
return new R<>(2023, "自定义的限流处理信息");
}
}
package com.afeiamic.springcloud.service;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Service;
@Service
public class FlowLimitService {
// 定义限流资源
@SentinelResource("common")
public String name() {
return "FlowLimitService";
}
}
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
# Nacos 服务注册中心地址
# server-addr: localhost:8848
server-addr: config-3344.com:1111
sentinel:
transport:
# 配置 Sentinel dashboard 地址
dashboard: localhost:8080
# 默认 8719 端口,假如被占用会自动从 8719 开始依次 +1 扫描 , 直至找到未被占用的端口
port: 8719 # Sentinel 控制台添加了一个限流规则,会把规则数据 push 给这个端口的 Http Server 接收
#web-context-unify: false # 关闭context整合
filter:
enabled: false
# 添加Nacos数据源配置
datasource:
flow-ds: # sentinel从nacos获取指定的流控规则 这个名字可以自定义,不重复就可以
nacos:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
username: nacos
password: nacos
dataId: ${spring.application.name}
groupId: DEFAULT_GROUP # 默认就是DEFAULT_GROUP
ruleType: flow # flow代表流程控制,degrade代表熔断规则
data-type: json # 默认就是json
management:
endpoints:
web:
exposure:
include: '*'
# 激活sentinel对feign的支持
feign:
sentinel:
enabled: true
\ No newline at end of file
......@@ -37,6 +37,9 @@
<module>cloudalibaba-consumer-nacos-order83</module>
<module>cloudalibaba-config-nacos-client3377</module>
<module>cloud-config-apollo-client3399</module>
<module>cloudalibaba-sentinel-service8401</module>
<module>cloudalibaba-provider-payment9003</module>
<module>cloudalibaba-consumer-nacos-order84</module>
</modules>
<!-- 统一管理jar包版本 -->
......@@ -72,7 +75,7 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<!--spring cloud alibaba 2.1.1.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册