目录
Gateway作用
在微服务项目中,没有引入网关时,项目架构如下:
引入网关后,架构如下:
引入网关后,有如下优势:
1、客户端请求经过网关向后台统一分发请求,后台微服务的增加、减少对客户端影响较小
2、客户端请求到每个后台微服务,可以经过网关实现统一的鉴权认证
3、网关可以对后台微服务做限流管理
Gateway使用
Gateway中有如下核心概念:
1、路由route:路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的 URL 和配置的路由匹配。
2、断言predicates:可以理解为匹配到路由的条件
3、过滤器Filter:对匹配的路由请求和响应进行处理
如下图配置信息,当访问http://网关ip:端口/blog-user/blogUser/getById,系统会将地址自动转发到 http://blog-user服务ip:端口/blogUser/getById 的这个请求中,并且注意,通过uri: lb://blog-user 这样的配置,如果系统存在多个blog-user服务实例,gateway网关会负载均衡(轮询)的方式转发的对应的blog-user服务实例
在微服务项目开发过程中,通常会建立一个网关项目,专门负责对各个微服务请求转发的管理,示例中建立了blog-gateway项目,步骤如下:
1、添加gateway依赖
由于gateway应用也会注册到nacos上,所以nacos服务发现的依赖也需要加上
2、配置网关信息
从下图中可以看出,配置了2个网关路由规则,
当网关请求地址是:http://localhost:7777/blog-user/blogUser/getById时,系统会从nacos找到 blog-user微服务名,进而请求到实际的地址:http://localhost:8088/blogUser/getById
当网关请求地址是:http://localhost:7777/blog-content/blogContent/getById?id=1时,系统会从nacos找到 blog-content微服务名,进而请求到实际的地址:http://localhost:8888/blogContent/getById?id=1 或 http://localhost:9999/blogContent/getById?id=1
blog-gateway注册在nacos中的信息如下:
blog-user注册在nacos中的信息如下:
blog-content注册在nacos中的信息如下:
3、实现网关自定义的过滤器
自定义过滤器分两种。全局过滤器:实现globalFilter和order接口。局部过滤器:实现AbstractGatewayFilterFactory接口并自定义或者使用父类的Config类 ,然后在配置文件中将过滤器进行配置(指明哪种路由用到自定义过滤器)。
下图自定义了网关过滤器CustomValidator,并配置在yml中,当请求网关地址:http://localhost:7777/blog-user/blogUser/getById 时,会先执行过滤器逻辑,然后再执行请求实际地址逻辑。
package com.gingko.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义过滤器 要在yml文件里配置自定义过滤器的过滤器名称CustomValidator (CustomValidatorGatewayFilterFactory)
* (GatewayFilterFactory是默认名称,前面的就是自定义过滤器的名称)
* filters:
* - CustomValidator=condition1,condition2,condition3,condition4
*/
@Order(1)
@Component
@Slf4j
public class CustomValidatorGatewayFilterFactory
extends AbstractGatewayFilterFactory<CustomValidatorGatewayFilterFactory.Config> {
public CustomValidatorGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
log.info("进入自定义过滤器...");
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String key = config.getParam();
log.info("参数信息:{},{},{},{}" ,config.getParam(),config.getParam2(),config.getParam3(),config.getParam4() );
return chain.filter(exchange);
});
}
/**
* 如果是自定义config 则需要重写该方法返回list集合 以便routdefine通过反射传回参数
* ShortcutConfiguratble 这个类获取配置
* RouteDefinitionRouteLocator.getFilters 获得所有过滤器 然后按顺序执行
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
List<String> list = new ArrayList<>();
list.add("param");
list.add("param2");
list.add("param3");
list.add("param4");
return list;
}
/**
* 你再路由配置那里给过滤器设置了多少参数那么就创建多少个参数变量来接收值
*/
static public class Config {
private String param;
private String param2;
private String param3;
private String param4;
public String getParam2() {
return param2;
}
public void setParam2(String param2) {
this.param2 = param2;
}
public String getParam3() {
return param3;
}
public void setParam3(String param3) {
this.param3 = param3;
}
public String getParam4() {
return param4;
}
public void setParam4(String param4) {
this.param4 = param4;
}
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
}
}
控制台运行结果如下:从日志时间上可以看出,请求网关地址:http://localhost:7777/blog-user/blogUser/getById 后,先执行的过滤器逻辑,打印输出了参数信息(p1,p2,p3,p4),然后执行了实际分发地址的逻辑。