简介
Gateway: Spring cloud Gateway是Spring公司基于Spring5.0,SpringBoot 2.0 和Project Reactor等技术开发的网关。它旨在为微服务架构提供一中简单有效且统一的Api路由管理方式。它的目标是代替NetflixZuul .
Sentinel: Sentinel 是面向分布式服务架构的高可用防护组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。

案例
SpringCloud + SpringCloud AliBaBa, Nacos做注册中心,Gateway网关,Sentinel熔断限流
创建主项目
创建普通maven项目
删除src文件夹
<?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.qc</groupId>
<artifactId>iaas</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<modules>
<module>gateway-server</module>
<module>authorization-server</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<cloud.alibaba.version>2021.0.1.0</cloud.alibaba.version>
<spring.boot.version>2.7.0</spring.boot.version>
<nacos.version>2021.1</nacos.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${cloud.alibaba.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<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-starter-alibaba-nacos-discovery</artifactId>
<version>${nacos.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
创建子Module
gateway-server authorization-server
项目结构:

gateway-server
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iaas</artifactId>
<groupId>com.qc</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway-server</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2021.1</version>
</dependency>
<!-- gateway 路由负载均衡支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- loadbalancer缓存 -->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.1</version>
</dependency>
</dependencies>
</project>
application.yml文件
server:
port: 80
spring:
application:
name: gateway-server
cloud:
nacos:
discovery:
server-addr: nacos-server:8848
gateway:
discovery:
locator:
# 启用getaway网关发现功能
enabled: true
# 启用小驼峰的服务名称访问服务
lower-case-service-id: true
#路由数组
routes:
# 路由标识 全局唯一
- id: authorization-server-router
# 转发到的地址 lb表示自动负载均衡
#authorization-server
uri: lb://authorization-server
# 优先级
order: 1
# 断言(就是路由转发需要的条件)
predicates:
# 当请求路径满足这个条件的时候进行转发
- Path=/test/**
# 过滤器 请求在转发过程中可以通过过滤器进行一定的修改
filters:
# 转发的时候去掉一层路径 比如前端访问/admin/login 转发的时候就成了/login
- StripPrefix=1
sentinel:
transport:
dashboard: localhost:8888
gatewayconfiguration 配置文件
package com.qc.config;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import javax.annotation.PostConstruct;
import java.util.*;
/**
* @author c
* @date 2022-06-08 02:07
*/
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
/**
* 配置限流规则
*/
@PostConstruct
private void initGatewayRules(){
//根据路由 id 限流
// Set<GatewayFlowRule> rules = new HashSet<>();
//// 限流的路径 gateway配置的路由标识
// rules.add(new GatewayFlowRule("authorization-server-router")
// //限流阈值
// .setCount(2)
// //多长时间
// .setIntervalSec(10));
//加载规则
// GatewayRuleManager.loadRules(rules);
//根据api分组限流
Set<GatewayFlowRule> rules = new HashSet<>();
//对分组为test_api的分组限流策略 setCount=多少次 setIntervalSec=多少秒
rules.add(new GatewayFlowRule("test_api").setCount(2).setIntervalSec(10));
GatewayRuleManager.loadRules(rules);
}
/**
* 自定义api分组
*/
@PostConstruct
public void initCustomizedApis(){
//创建一个集合存放具体的分组信息
Set<ApiDefinition> definitions = new HashSet<>();
//用户自定义的 API 定义分组
ApiDefinition apiDefinition = new ApiDefinition("test_api");
//分组包含的路径集合
Set<ApiPredicateItem> apiPredicateItems = new HashSet<>();
//创建配置那些路径匹配规则类对象
ApiPathPredicateItem apiPathPredicateItem = new ApiPathPredicateItem();
// /test/**这类路径根据URL_MATCH_STRATEGY_PREFIX来匹配
apiPathPredicateItem.setPattern("/test/**").setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX);
//添加到集合
apiPredicateItems.add(apiPathPredicateItem);
//添加到分组
apiDefinition.setPredicateItems(apiPredicateItems);
//添加到存放分组信息集合
definitions.add(apiDefinition);
//加载自定义api分组
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
/**
* 限流返回信息
*/
@PostConstruct
public void initBlockHandlers(){
BlockRequestHandler blockRequestHandler = (serverWebExchange, throwable) ->
ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).bodyValue("{" +
" \"msg\":\"被限流了!\" " +
"}");
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
package com.qc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author c
* @date 2022-06-06 15:14
*/
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
authorization-server
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>iaas</artifactId>
<groupId>com.qc</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>authorization-server</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
application.yml配置文件
server:
port: 8080
spring:
application:
name: authorization-server
cloud:
nacos:
discovery:
server-addr: nacos-server
controller
package com.qc.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author c
* @date 2022-06-06 15:20
*/
@RestController
public class Hello {
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}
package com.qc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author c
* @date 2022-06-06 15:30
*/
@SpringBootApplication
@EnableDiscoveryClient
public class AuthorizationApplication {
public static void main(String[] args) {
SpringApplication.run(AuthorizationApplication.class,args);
}
}
下载sentinel控制台(可下可不下)
下载地址:https://github.com/alibaba/Sentinel/releases
运行指令:
#官方
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
# 测试环境 本地装的jdk17 17不允许反射,需要额外参数--add-exports=java.base/sun.net.util=ALL-UNNAMED
java -jar --add-exports=java.base/sun.net.util=ALL-UNNAMED -Dserver.port=8888 sentinel-dashboard-1.8.4.jar
访问本地 localhost:8888
帐号密码默认都是: sentinel

结果

访问 网关 符合/test/**的请求转发到authorization-server服务去了 说明网关实现

连续访问3次以上,返回限流信息,说明sentinel限流成功。