什么是网关?干什么用的?
• 网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。
• 在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务
的接口完成一个用户请求。
• 存在的问题:
• 客户端多次请求不同的微服务,增加客户端的复杂性
• 认证复杂,每个服务都要进行认证
• http请求不同服务次数增加,性能不高
• 网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,
诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等
• 在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等
网关也是一个应用,有了网关之后,我们所有的请求都访问网关应用,由网关帮我们去调用其他服务。
网关的主要功能有两个:
- 路由
- 过滤
Gateway 网关
什么是Gateway 网关:
SpringCloud Gateway 是 Spring Cloud 的一个全新项目,基于 Spring 5.0+Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
以上的概述是spring官网给出的,已经非常便于大家的理解了,当然我们可以用下图来让大家更清楚的理解,微服务中的网关用在了哪里。
如何搭建一个网关呢?
操作步骤:
-
搭建网关模块,创建一个最基本的spring cloud模块。
-
引入依赖:starter-gateway
<dependencies> <!--引入gateway 网关--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- eureka-client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
-
编写启动类,无特殊操作
@SpringBootApplication @EnableEurekaClient public class ApiGatewayApp { public static void main(String[] args) { SpringApplication.run(ApiGatewayApp.class,args); } }
-
编写配置文件
server: port: 80 spring: application: name: api-gateway-server cloud: # 网关配置 gateway: # 路由配置:转发规则 routes: #集合。 # id: 唯一标识。默认是一个UUID # uri: 转发路径 # predicates: 条件,用于请求网关路径的匹配规则 - id: gateway-provider # 静态路由 uri: http://localhost:8001/ predicates: - Path=/goods/** - id: gateway-cum uri: http://localhost:9000/ predicates: - Path=/orders/**
上面我们使用的是静态路由
要知道静态路由,在网关中uri的配置是写死的,不便于维护。
所以我们实际工作中都是使用动态路由,让网关应用能够从注册中心Eureka中,动态的通过应用的名称来获取应用的地址
动态路由
- id: gateway-consumer # uri: http://localhost:9000 uri: lb://GATEWAY-CONSUMER predicates: - Path=/order/** eureka: client: service-url: defaultZone: http://localhost:8761/eureka
Gateway 网关 – 过滤器
过滤器
-
Gateway 支持过滤器功能,对请求或响应进行拦截,完成一些通用操作。
-
Gateway 提供两种过滤器方式:“pre”和“post”
• pre 过滤器,在转发之前执行,可以做参数校验、权限校验、流量监控、日志输出、协议转换等。
• post 过滤器,在响应之前执行,可以做响应内容、响应头的修改,日志的输出,流量监控等。 -
Gateway 还提供了两种类型过滤器
• GatewayFilter:局部过滤器,针对单个路由
• GlobalFilter :全局过滤器,针对所有路由
局部过滤器
• GatewayFilter 局部过滤器,是针对单个路由的过滤器。
• 在Spring Cloud Gateway 组件中提供了大量内置的局部过滤器,对请求和响应做过滤操作。
• 遵循约定大于配置的思想,只需要在配置文件配置局部过滤器名称,并为其指定对应的值,就可以让其生效。
配置:
# filters:配置局部过滤器的
- id: gateway-provider
# 静态路由
# uri: http://localhost:8001/
# 动态路由
uri: lb://GATEWAY-PROVIDER
predicates:
- Path=/goods/**
filters:
- AddRequestParameter=username,zhangsan #过滤器工厂会在匹配的请求头加上一对请求头,名称为username-Id值为zhangsan
总结: 根据文档中的过滤器的作用和名称进行配置,过滤的参数和值之间使用,逗号分隔。
自定义全局过滤器
• GlobalFilter 全局过滤器,不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上。
• Spring Cloud Gateway 核心的功能也是通过内置的全局过滤器来完成。
• 自定义全局过滤器步骤:
- 定义类实现 GlobalFilter 和 Ordered接口
- 复写方法
- 完成逻辑处理
@Component
public class MyFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("自定义全局过滤器执行了~~~");
//获取web应用的对象
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
return chain.filter(exchange);//放行
}
/**
* 过滤器排序
* @return 数值越小 越先执行
*/
@Override
public int getOrder() {
return 0;
}
}
总结:
自定义全局过滤器无需配置,只需要实现接口中的方法就可以。
自定义的过滤器需要添加@Component交给spring容器管理。
最后给大家留一个较为完整的yml配置
server:
port: 80
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能
lower-case-service-id: true #使用小写服务名,默认是大写
routes:
- id: gateway-provider #gateway-provider #路由的ID,没有固定规则但要求唯一,建议配合服务名
uri: lb://GATEWAY-CONSUMER #匹配后的目标服务地址,供服务的路由地址
#uri: http://localhost:9000 #匹配后提供服务的路由地址
filters:
- AddRequestParameter=username,zhangsan #过滤器工厂会在匹配的请求头加上一对请求头
predicates:
- Path=/goods/** # 断言,路径相匹配的进行路由
- Method=GET,POST
eureka:
instance:
hostname: cloud-gateway-service
client: #服务提供者provider注册进eureka服务列表内
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://localhost:8761/eureka