0.概述
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/
1.入门配置
1.1 POM
<!--新增gateway-->
<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>
1.2 YML
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: payment-route
uri: lb://cloud-order-service
predicates:
- Path=/v2/order/**
filters:
- StripPrefix=1
nacos:
discovery:
server-addr: 192.168.2.18:8848
inetutils:
ignored-interfaces: ['VMware.*']
1.3 主启动类
@SpringBootApplication
public class GateWayMain {
public static void main(String[] args) {
SpringApplication.run(GateWayMain.class, args);
}
}
1.4 测试
localhost:9527/v2/order/
2.Predicate的使用
cs
pring:
cloud:
gateway:
routes:
- id: before_route
uri: lb://cloud-order-service
predicates:
# 在某个时间之前的请求才会被转发到 http://localhost:8001,
- Before=2017-01-20T17:42:47.789+08:00[Asia/Shanghai]
# 在某个时间之后的请求才会被转发
# - After=2017-01-20T17:42:47.789+08:00[Asia/Shanghai]
# 在某个时间段之间的才会被转发
# - Between=2017-01-20T17:42:47.789+08:00[Asia/Shanghai], 2017-01-21T17:42:47.789+08:00[Asia/Shanghai]
# 名为chocolate的表单或者满足正则ch.p的表单才会被匹配到进行请求转发
# - Cookie=chocolate, ch.p
# 携带参数X-Request-Id或者满足\d+的请求头才会匹配
# - Header=X-Request-Id, \d+
# 按Host主机名匹配
# - Host=qiying.com:8080
# 按请求方法进行匹配,只有GET方法才会匹配
# - Method=GET
# 按请求路径进行匹配
# - Path=/app/{path}
filters:
# 在请求路径前加上自定义的路径
# - PrefixPath=/app
# 重写请求路径
# 访问localhost:8080/test, 请求会转发到localhost:8001/app/test
# - RewritePath=/test, /app/test
# - RewritePath=(?<oldPath>^/), /app$\{oldPath}
# 通过模板设置路径
# - SetPath=/app/{path}
3.Filter的使用
3.1 自定义全局过滤器
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Date;
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: "+new Date());
String name = exchange.getRequest().getQueryParams().getFirst("username");
if(StringUtils.isEmpty(name))
{
log.info("*****用户名为Null 非法用户,(┬_┬)");
exchange.getResponse().setRawStatusCode(HttpStatus.NOT_ACCEPTABLE.value());
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
3.2 令牌桶算法限流
-
YML配置
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: cloud-order-service
uri: lb://cloud-order-service
predicates:
- Path=/v2/**
- After=2024-02-17T10:41:00.000+08:00[Asia/Shanghai]
filters:
- name: StripPrefix
args:
parts: 1
- name: RequestRateLimiter
args:
keyResolver: '#{@myKeyResolver}'
redis-rate-limiter.replenishRate: 1 #生产令牌速度,每秒多少个
redis-rate-limiter.burstCapacity: 5 #令牌桶容量
nacos:
discovery:
server-addr: 192.168.2.18:8848
inetutils:
ignored-interfaces: ['VMware.*']
redis:
host: 192.168.2.18
password: 123456 -
创建MyKeyResolver类
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
public class MyKeyResolver implements KeyResolver {@Override public Mono<String> resolve(ServerWebExchange exchange) { String address = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); return Mono.just(address); }
}
-
request_rate_limiter.lua
local tokens_key = KEYS[1]
local timestamp_key = KEYS[2]
--redis.log(redis.LOG_WARNING, "tokens_key " .. tokens_key)local rate = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])local fill_time = capacity/rate
local ttl = math.floor(fill_time*2)--redis.log(redis.LOG_WARNING, "rate " .. ARGV[1])
--redis.log(redis.LOG_WARNING, "capacity " .. ARGV[2])
--redis.log(redis.LOG_WARNING, "now " .. ARGV[3])
--redis.log(redis.LOG_WARNING, "requested " .. ARGV[4])
--redis.log(redis.LOG_WARNING, "filltime " .. fill_time)
--redis.log(redis.LOG_WARNING, "ttl " .. ttl)local last_tokens = tonumber(redis.call("get", tokens_key))
if last_tokens == nil then
last_tokens = capacity
end
--redis.log(redis.LOG_WARNING, "last_tokens " .. last_tokens)local last_refreshed = tonumber(redis.call("get", timestamp_key))
if last_refreshed == nil then
last_refreshed = 0
end
--redis.log(redis.LOG_WARNING, "last_refreshed " .. last_refreshed)local delta = math.max(0, now-last_refreshed)
local filled_tokens = math.min(capacity, last_tokens+(delta*rate))
local allowed = filled_tokens >= requested
local new_tokens = filled_tokens
local allowed_num = 0
if allowed then
new_tokens = filled_tokens - requested
allowed_num = 1
end--redis.log(redis.LOG_WARNING, "delta " .. delta)
--redis.log(redis.LOG_WARNING, "filled_tokens " .. filled_tokens)
--redis.log(redis.LOG_WARNING, "allowed_num " .. allowed_num)
--redis.log(redis.LOG_WARNING, "new_tokens " .. new_tokens)redis.call("setex", tokens_key, ttl, new_tokens)
redis.call("setex", timestamp_key, ttl, now)return { allowed_num, new_tokens }
-
如果请求每秒超过5个,将无法访问, 执行的类,RedisRateLimiter.isAllowed
3.3 自定义断言过滤器
-
创建过滤器
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.Arrays;
import java.util.List;@Component
@Slf4j
public class XXGatewayFilterFactory extends AbstractGatewayFilterFactory<XXGatewayFilterFactory.Config> {public XXGatewayFilterFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("path"); } @Override public GatewayFilter apply(Config config) { return new GatewayFilter() { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("xx-GatewayFilter-filter"); return chain.filter(exchange); } }; } public static class Config { public String getPath() { return path; } public void setPath(String path) { this.path = path; } private String path; }
}
-
YML
spring:
cloud:
gateway:
routes:
- id: cloud-order-service
uri: lb://cloud-order-service
predicates:
- Path=/v2/**
- After=2024-02-17T10:41:00.000+08:00[Asia/Shanghai]
filters:
- name: XX
3.4
4.跨域
spring:
application:
name: cloud-gateway
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedHeaders: "*"
allowedOrigins: "*"
allowedMethods: "*"