零、人在月球
目录
零、人在月球
一、功能简介
1、网关是一个服务:
二、Gateway 断言
1、path断言
2、Query断言
3、Method断言
4、Host断言
6、Header断言
7、Weight 权重路由
8、After 时间路由
9、Before 时间路由
10、Between时间区间路由
11、灰度发布
三、Gateway 过滤器
1、增加header 请求头
2、新增动态header请求头
3、设置请求头 过滤器配置,修改移除请求头
4、PreserverHostHeader
5、重写response加密密码
6、response去重
7、路径带前缀 请求/get/app 其实是/prefix/get
8、配置30几 跳转到指定地址
9、修改状态码
10、转发地址
11、去掉增加 请求路径中部分层级
12、重试过滤器
13、过滤器设置请求大小
14、spring-session
15、默认filter
四、熔断机制
1、老熔断
2、熔断机制-新的
五、限流配置
1、增加依赖
2、配置redis:spring.redis.database:XX
3、配置keyResolver,参考类RateLimiteConfig
4、ym配置spring.cloud.gateway.routes
5、当发生限流,会向redis存储两个数据 .限流返回状态码是429
6、配置文件RateLimiteConfig.java
六、自定义谓词配置类
1、配置类UserNameCheckRoutePredicateFactory.java
2、配置项
七、自定义过滤器
1、配置类
pre配置类
post过滤器
3、配置文件
八、全局过滤器
九、网关超时配置
十、元数据 metadata
十一、gateway内置API与跨域
1、API说明:
2、打开端点配置
3、跨域请求:
一、功能简介
1、网关是一个服务:
路由:使用webflux、缓存、权重和灰度发布、随机算法
过滤器:有序
限流:内置令牌桶+Redis 整合GoogleGuava
权限
hystrix 熔断
声明周期
二、Gateway 断言
断言:predicates 多断言可以配合使用
1、path断言
predicates:
-Path=/mg
2、Query断言
参数值可以写正则,也可以只写参数名
predicates:
-Query=foo,ba.
3、Method断言
predicates:
-Method=get
4、Host断言
predicates:
-Host=mashibing.com
5、cookie断言
predicates:
-cookie=name,yiming
6、Header断言
predicates:
-Header=reqId,9090d+ #正则表达式d+ 数字
7、Weight 权重路由
- id: weight2
uri: http://localhost:6601
predicates:
- Path=/api
@Configuration
public class RateLimiteConfig{
//ip限流 1s 100次
//userId限流 1s 100次
//路径限流
@Bean
@Primary #如果不使用 @Primary 注解,项目启动会报错
public KeyResolver pathKeyResolver(){
//写法1
// return exchange-> Mono.just(
// exchange.getRequest()
// .getPath()
// .toString()
// );
//写法2
return new KeyResolver(){
@Override
public Mono resolve(ServerWebExchange exchange){
return Mono.just(exchange.getRequest()
.getPath()
.toString());
}
};
}
//根据请求IP限流
@Bean
public KeyResolver ipKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getRemoteAddress()
.getHostName()
);
}
//根据userid限流
@Bean
public KeyResolver userKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getQueryParams()
.getFirst("userId")
);
}
}
六、自定义谓词配置类
predicates:
-Path=/mg
参数值可以写正则,也可以只写参数名
predicates:
-Query=foo,ba.
3、Method断言
predicates:
-Method=get
4、Host断言
predicates:
-Host=mashibing.com
5、cookie断言
predicates:
-cookie=name,yiming
6、Header断言
predicates:
-Header=reqId,9090d+ #正则表达式d+ 数字
7、Weight 权重路由
- id: weight2
uri: http://localhost:6601
predicates:
- Path=/api
@Configuration
public class RateLimiteConfig{
//ip限流 1s 100次
//userId限流 1s 100次
//路径限流
@Bean
@Primary #如果不使用 @Primary 注解,项目启动会报错
public KeyResolver pathKeyResolver(){
//写法1
// return exchange-> Mono.just(
// exchange.getRequest()
// .getPath()
// .toString()
// );
//写法2
return new KeyResolver(){
@Override
public Mono resolve(ServerWebExchange exchange){
return Mono.just(exchange.getRequest()
.getPath()
.toString());
}
};
}
//根据请求IP限流
@Bean
public KeyResolver ipKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getRemoteAddress()
.getHostName()
);
}
//根据userid限流
@Bean
public KeyResolver userKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getQueryParams()
.getFirst("userId")
);
}
}
六、自定义谓词配置类
predicates:
-Method=get
predicates:
-Host=mashibing.com
5、cookie断言
predicates:
-cookie=name,yiming
6、Header断言
predicates:
-Header=reqId,9090d+ #正则表达式d+ 数字
7、Weight 权重路由
- id: weight2
uri: http://localhost:6601
predicates:
- Path=/api
@Configuration
public class RateLimiteConfig{
//ip限流 1s 100次
//userId限流 1s 100次
//路径限流
@Bean
@Primary #如果不使用 @Primary 注解,项目启动会报错
public KeyResolver pathKeyResolver(){
//写法1
// return exchange-> Mono.just(
// exchange.getRequest()
// .getPath()
// .toString()
// );
//写法2
return new KeyResolver(){
@Override
public Mono resolve(ServerWebExchange exchange){
return Mono.just(exchange.getRequest()
.getPath()
.toString());
}
};
}
//根据请求IP限流
@Bean
public KeyResolver ipKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getRemoteAddress()
.getHostName()
);
}
//根据userid限流
@Bean
public KeyResolver userKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getQueryParams()
.getFirst("userId")
);
}
}
六、自定义谓词配置类
predicates:
-cookie=name,yiming
predicates:
-Header=reqId,9090d+ #正则表达式d+ 数字
7、Weight 权重路由
- id: weight2
uri: http://localhost:6601
predicates:
- Path=/api
@Configuration
public class RateLimiteConfig{
//ip限流 1s 100次
//userId限流 1s 100次
//路径限流
@Bean
@Primary #如果不使用 @Primary 注解,项目启动会报错
public KeyResolver pathKeyResolver(){
//写法1
// return exchange-> Mono.just(
// exchange.getRequest()
// .getPath()
// .toString()
// );
//写法2
return new KeyResolver(){
@Override
public Mono resolve(ServerWebExchange exchange){
return Mono.just(exchange.getRequest()
.getPath()
.toString());
}
};
}
//根据请求IP限流
@Bean
public KeyResolver ipKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getRemoteAddress()
.getHostName()
);
}
//根据userid限流
@Bean
public KeyResolver userKeyResolver(){
return exchange -> Mono.just(
exchange.getRequest()
.getQueryParams()
.getFirst("userId")
);
}
}
六、自定义谓词配置类
可以保存数据库,存储。
1、配置类UserNameCheckRoutePredicateFactory.java
package com.pig4cloud.pig.demo.util;
import com.mysql.cj.util.StringUtils;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import javax.validation.constraints.NotEmpty;
import java.util.function.Predicate;
@Component
public class UserNameCheckRoutePredicateFactory extends AbstractRoutePredicateFactory {
public UserNameCheckRoutePredicateFactory(){
super(Config.class);
}
@Override
public Predicate apply(UserNameCheckRoutePredicateFactory.Config config) {
//写法1
return new Predicate() {
@Override
public boolean test(ServerWebExchange exchange) {
String userName = exchange.getRequest().getQueryParams().getFirst("userName");
if(StringUtils.isNullOrEmpty(userName)){
return false;
}
//检查请求参数中userName是否与配置的数据相同,如果相同则允许访问,否则不允许访问
if(userName.equals(config.getName())){
return true;
}
return false;
}
};
}
@Validated
public static class Config{
@NotEmpty
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
2、配置项
spring.cloud.gateway
routes:
-id: Auth_route
uri: lb://mima-cloud-producer
order:1
predicates:
-Path=
@Component
public class MyAddRequestHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory {
public MyAddRequestHeaderGatewayFilterFactory(){super(Config.class);}
@Override
public GatewayFilter apply(Config config){
//写法一
// return new GatewayFilter() {
// @Override
// public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// System.out.println("MyAddRequestHeaderGatewayFilterFactory.apply is run...");
// //exchange.getRequest().mutate() //目的是转化为装饰类,否则request为只读的,不能操作
// //header方法用来设置header的值
// ServerHttpRequest request = exchange.getRequest().mutate().header(config.getName(),config.getValue()).build();
// //将request包裹继续向下传递
// return chain.filter(exchange.mutate().request(request).build());
// }
// }
return (exchange, chain) -> {
System.out.println("MyAddRequestHeaderGatewayFilterFactory.apply is run...");
//exchange.getRequest().mutate() //目的是转化为装饰类,否则request为只读的,不能操作
//header方法用来设置header的值
ServerHttpRequest request=exchange.getRequest().mutate().header(config.getName(),config.getValue()).build();
return chain.filter(exchange.mutate().request(request).build());
//response可以直接写
// exchange.getResponse().getHeaders().set(config.getName(),config.getValue());
// return chain.filter(exchange);
};
}
@Validated
public static class Config{
@NotEmpty
private String name;
@NotEmpty
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
post过滤器
@Component
public class PostLogGatewayFilterFactory extends AbstractGatewayFilterFactory {
@Override
public GatewayFilter apply(Object config){
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(()-> {
System.out.println("PostLogGatewayFilterFactory is run...");
}));
};
}
}
3、配置文件
spring.cloud.gateway.routes
-id: MyFilter
uri: lb://mima-cloud
order: 1
predicates:
-Path=
@Configuration
public class GlobalFilterConfig {
//order 越小,越先执行
@Bean
@Order(-1)
public GlobalFilter globalFilter1(){
return (exchange, chain) -> {
System.out.println("pro filter globalFilter1...");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("post filter globalFilter1...");
}));
};
}
@Bean
@Order(1)
public GlobalFilter globalFilter2(){
return (exchange, chain) -> {
System.out.println("pro filter globalFilter2...");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("post filter globalFilter2...");
}));
};
}
}
spring.cloud.gateway
routes:
-id: Auth_route
uri: lb://mima-cloud-producer
order:1
predicates:
-Path=
@Component
public class MyAddRequestHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory {
public MyAddRequestHeaderGatewayFilterFactory(){super(Config.class);}
@Override
public GatewayFilter apply(Config config){
//写法一
// return new GatewayFilter() {
// @Override
// public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// System.out.println("MyAddRequestHeaderGatewayFilterFactory.apply is run...");
// //exchange.getRequest().mutate() //目的是转化为装饰类,否则request为只读的,不能操作
// //header方法用来设置header的值
// ServerHttpRequest request = exchange.getRequest().mutate().header(config.getName(),config.getValue()).build();
// //将request包裹继续向下传递
// return chain.filter(exchange.mutate().request(request).build());
// }
// }
return (exchange, chain) -> {
System.out.println("MyAddRequestHeaderGatewayFilterFactory.apply is run...");
//exchange.getRequest().mutate() //目的是转化为装饰类,否则request为只读的,不能操作
//header方法用来设置header的值
ServerHttpRequest request=exchange.getRequest().mutate().header(config.getName(),config.getValue()).build();
return chain.filter(exchange.mutate().request(request).build());
//response可以直接写
// exchange.getResponse().getHeaders().set(config.getName(),config.getValue());
// return chain.filter(exchange);
};
}
@Validated
public static class Config{
@NotEmpty
private String name;
@NotEmpty
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
post过滤器
@Component
public class PostLogGatewayFilterFactory extends AbstractGatewayFilterFactory {
@Override
public GatewayFilter apply(Object config){
return (exchange, chain) -> {
return chain.filter(exchange).then(Mono.fromRunnable(()-> {
System.out.println("PostLogGatewayFilterFactory is run...");
}));
};
}
}
3、配置文件
spring.cloud.gateway.routes
-id: MyFilter
uri: lb://mima-cloud
order: 1
predicates:
-Path=
@Configuration
public class GlobalFilterConfig {
//order 越小,越先执行
@Bean
@Order(-1)
public GlobalFilter globalFilter1(){
return (exchange, chain) -> {
System.out.println("pro filter globalFilter1...");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("post filter globalFilter1...");
}));
};
}
@Bean
@Order(1)
public GlobalFilter globalFilter2(){
return (exchange, chain) -> {
System.out.println("pro filter globalFilter2...");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("post filter globalFilter2...");
}));
};
}
}
spring.cloud.gateway.routes
-id: MyFilter
uri: lb://mima-cloud
order: 1
predicates:
-Path=
@Configuration
public class GlobalFilterConfig {
//order 越小,越先执行
@Bean
@Order(-1)
public GlobalFilter globalFilter1(){
return (exchange, chain) -> {
System.out.println("pro filter globalFilter1...");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("post filter globalFilter1...");
}));
};
}
@Bean
@Order(1)
public GlobalFilter globalFilter2(){
return (exchange, chain) -> {
System.out.println("pro filter globalFilter2...");
return chain.filter(exchange).then(Mono.fromRunnable(()->{
System.out.println("post filter globalFilter2...");
}));
};
}
}
应答顺序为:pro filter globalFilter1...
pro filter globalFilter2...
post filter globalFilter2...
post filter globalFilter1...
九、网关超时配置
spring.cloud.gateway.httpclient.connect-timeout=1000 #连接超时 毫秒
spring.cloud.gateway.httpclient.response-timeout=5s #应答超时 java.time.Duration http状态码504
十、元数据 metadata
十一、gateway内置API与跨域
1、API说明:
/actuator/gateway/routes/{id} ,method=[DELETE] 删除单个路由
/actuator/gateway/routes/{id},method=[POST] 新增单个路由
/actuator/gateway/routes/{id},method=[GET] 查看单个路由
/actuator/gateway/routes ,method=[GET] 查看路由列表
/actuator/gateway/refresh,method=[POST] 路由刷新
/actuator/gateway/globalfilters,method=[GET]获取全局过滤器列表
/actuator/gateway/routefilters,method=[GET] 路由过滤器工厂列表
2、打开端点配置
management.endpoint.gateway.enabled=true
3、跨域请求:
spring.cloud.gateway.httpclient.connect-timeout=1000 #连接超时 毫秒
spring.cloud.gateway.httpclient.response-timeout=5s #应答超时 java.time.Duration http状态码504
十一、gateway内置API与跨域
1、API说明:
/actuator/gateway/routes/{id} ,method=[DELETE] 删除单个路由
/actuator/gateway/routes/{id},method=[POST] 新增单个路由
/actuator/gateway/routes/{id},method=[GET] 查看单个路由
/actuator/gateway/routes ,method=[GET] 查看路由列表
/actuator/gateway/refresh,method=[POST] 路由刷新
/actuator/gateway/globalfilters,method=[GET]获取全局过滤器列表
/actuator/gateway/routefilters,method=[GET] 路由过滤器工厂列表
2、打开端点配置
management.endpoint.gateway.enabled=true
3、跨域请求:
/actuator/gateway/routes/{id} ,method=[DELETE] 删除单个路由
/actuator/gateway/routes/{id},method=[POST] 新增单个路由
/actuator/gateway/routes/{id},method=[GET] 查看单个路由
/actuator/gateway/routes ,method=[GET] 查看路由列表
/actuator/gateway/refresh,method=[POST] 路由刷新
/actuator/gateway/globalfilters,method=[GET]获取全局过滤器列表
/actuator/gateway/routefilters,method=[GET] 路由过滤器工厂列表
2、打开端点配置
management.endpoint.gateway.enabled=true
3、跨域请求:
配置文件-直接引用即可
package com.pig4cloud.pig.demo.util;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
@Configuration
public class CorsConfig {
private static final String MAX_AGE="18000L";
@Bean
public WebFilter corsFilter(){
return (ServerWebExchange ctx, WebFilterChain chain)->{
System.out.println("corsFilter... run");
ServerHttpRequest request = ctx.getRequest();
if(!CorsUtils.isCorsRequest(request)){
return chain.filter(ctx);
}
HttpHeaders requestHeaders=request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpMethod requestMethod= requestHeaders.getAccessControlRequestMethod();
HttpHeaders headers=response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestHeaders.getOrigin());
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlAllowHeaders());
if(requestMethod!=null){
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,requestMethod.name());
}
//携带cookie
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS,"*");
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
if(request.getMethod() == HttpMethod.OPTIONS){
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(ctx);
};
}
}
荆轲刺秦王!



