静态配置请求路由
1、依赖:
<?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>nacos-register</artifactId>
<groupId>com.bear</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos_gateway_server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--将服务注册到nacos中-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
yaml配置:
server:
port: 8021
spring:
application:
name: api-gateway # 指定服务名
cloud:
gateway:
routes: # gateway动态路由,从nacos中动态获取服务
- id: product-service # 唯一性的id
uri: lb://nacos-provide # nacos上服务的名称,前面的lb是必须要的
predicates:
- Path=/provide/** # 当端口后面有带'/provide参数的时候,则去nacos中获取上面的服务名,然后跳转到目标服务做请求
nacos:
discovery: # 注册中心
server-addr: 127.0.0.1:8850
注:uri : uri以 lb: //开头(lb代表从注册中心获取服务),后面接的就是你需要转发到的服务名称。
重要的是 predicates:
- Path=/provide/**
只要匹配上了,就会调转到其他服务,请求其他服务的时候,端口号后面会带上前缀provide
动态配置请求路由
去掉端口号后面的请求前缀
yaml配置:
server:
port: 8021
spring:
application:
name: api-gateway # 指定服务名
cloud:
gateway:
routes: # gateway动态路由,从nacos中动态获取服务
- id: product-service
uri: lb://nacos-provide # nacos上服务的名称,前面的lb是必须要的
predicates:
- Path=/product-service/** # 当端口后面有带'/provide参数的时候,则去nacos中获取上面的服务名,然后跳转到目标服务做请求
filters:
- RewritePath=/product-service/(?<segment>.*), /$\{segment} # #配置路由过滤器,将当前请求http://127.0.0.1:8021/product-service/provide/provideGet --》 http://127.0.0.1:8095/provide/provideGet
nacos:
discovery: # 注册中心
server-addr: 127.0.0.1:8850
注:1、product-service为瞎写的名称,可以自定义
2、加上filters 下面的 - RewritePath,这样就可以在调转其他服务的时候,去掉前缀,而只加真正的请求url
过滤器
一、过滤器的生命周期
Spring Cloud Gateway 的 Filter 的生命周期不像 Zuul 的那么丰富,它只有两个:“pre” 和 “post”。
PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择
请求的微服务、记录调试信息等。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP
Header、收集统计信息和指标、将响应从微服务发送给客户端等。
二、过滤器类型
Spring Cloud Gateway 的 Filter 从作用范围可分为另外两种GatewayFilter 与 GlobalFilter。
GatewayFilter:应用到单个路由或者一个分组的路由上。
GlobalFilter:应用到所有的路由上。
过滤器有:局部过滤器和全局过滤器。 过滤器类很多,可查找网上的
三、统一鉴权
统一鉴权在网关中做:
当客户端第一次请求服务时,服务端对用户进行信息认证(登录) 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证
以后每次请求,客户端都携带认证的token 服务端对token进行解密,判断是否有效。
看我的博客:springsecurity权限管理
https://editor.csdn.net/md/?articleId=121249463
四、网关限流
令牌桶算法
令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用
的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令
牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令
牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的
进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这
时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就
已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时
的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。
SpringCloudGateway官方就提供了基于令牌桶的限流支持。基于其内置的过滤器工厂
RequestRateLimiterGatewayFilterFactory 实现。在过滤器工厂中是通过Redis和lua脚本结合的方
式进行流量控制。
setinel做限流:
package com.bear.configuration;
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.exception.SentinelGatewayBlockExceptionHandler;
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.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author LiuShanshan
* @version V1.0
* @Description
*/
@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;
}
/*** 配置限流的异常处理器:SentinelGatewayBlockExceptionHandler */
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
/*** 配置限流过滤器 */
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
/*** 配置初始化的限流参数 */
@PostConstruct
public void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<GatewayFlowRule>();
rules.add( new GatewayFlowRule("nacos-consumer-sentinel") //资源名称
.setCount(1) // 限流阈值
.setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
);
GatewayRuleManager.loadRules(rules);
}
}
yaml配置
server:
port: 8021
spring:
application:
name: api-gateway # 指定服务名
redis:
host: 127.0.0.1
port: 6379
database: 0
cloud:
gateway:
routes: # 1、gateway动态路由,从nacos中动态获取服务
- id: product-service
uri: lb://nacos-provide # nacos上服务的名称,前面的lb是必须要的
predicates:
- Path=/product-service/** # 当端口后面有带'/provide参数的时候,则去nacos中获取上面的服务名,然后跳转到目标服务做请求
filters:
- RewritePath=/product-service/(?<segment>.*), /$\{segment} # #配置路由过滤器,将当前请求http://127.0.0.1:8021/product-service/provide/provideGet --》 http://127.0.0.1:8095/provide/provideGet
# 2、下面配置的是限流过滤器,令牌木桶总容量为3,每1秒产生1个
# - name: RequestRateLimiter # 配置 RequestRateLimiter的限流过滤器
# args:
# # 使用SpEL从容器中获取对象
# key-resolver: '#{@pathKeyResolver}'
# # 令牌桶每秒填充平均速率
# redis-rate-limiter.replenishRate: 1
# # 令牌桶的总容量
# redis-rate-limiter.burstCapacity: 3
nacos:
discovery: # 注册中心
server-addr: 127.0.0.1:8850