什么是网关
网关是一种充当转换重任的计算机系统或设备,使用在不同的通信协议、数据格式或语言,甚至网关是一种充当转换重任的计算机系统或设备,使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间进行数据传输.
网关具备转发, 路由和数据过滤的功能, 它能够识别不同网络中的数据包, 并根据器目的地址和源地址决定如何转发数据. 同时, 网关还可以实施网络安全策略, 对进出的数据包进行检查和过滤, 保护网络安全.
网关在互联网中起到重要作用, 它连接了内部局域网好外部互联网, 使得数据能够在不同网络之间传递和交换.
网关有什么作用
路由功能: 根据目标地址的不同选择最佳的路径
安全控制(统一认证授权): 对进出的数据包进行检查和过滤, 它可以授权来自源网络的数据包, 并且阻止未授权的访问.
协议转换: 网关可以进行协议转换, 使得不同的网络设备可以进行通信, 例如: 将 HTTPS 转换成 HTTP.
网络地址转换(NAT): 将内部网络使用的私有 IP 地址转换成外部网络使用的公共 IP 地址.
Spring Cloud GateWay 组成
路由(Route): 定义了请求应该被转发到哪个目标地址. 路由由 ID, 目标URI, 断言好过滤器组成. 通过配置多个路由, 可以实现不同请求的路由规则.
断言(Predicate): 用于匹配请求的条件, 如果请求匹配断言条件, 则会被路由转发到对应的目标地址.
过滤器(Filter): 用于请求路由前或请求后进行一些处理, 如添加头部信息, 修改请求体等.
Spring Cloud GateWay 基础使用
添加依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
注意: Spring Cloud GateWay 底层是基于响应式 Reactor Web 实现的已经包含了 Web 所以这两个依赖同时引入就会报错
设置路由规则
server: port: 10086 spring: cloud: gateway: routes: - id: user-service uri: http://localhost:9090 predicates: - Path=/user/**, /userlog/** # 匹配多个路径时可以用英文逗号隔开 - id: order-service uri: http://localhost:9091 predicates: - Path=/order/**
断言类型
Spring Cloud GateWay 目前支持 12 种断言类型
After: 请求在指定时间之后才能匹配
Before: 请求在指定时间之前才能匹配
Between: 请求在指定时间中才能匹配
Cookie: 匹配请求中的 Cookie 值
Header: 匹配请求中的 Header 值
Host: 匹配请求头中的 Host 值
Method: 匹配请求头中的 Method 值
Path: 匹配请求路径
Query: 匹配请求参数
RemoteAddr: 匹配请求的 IP 地址
Weight: 根据权重分发请求
XDorwardedRemoteAddr: 根据 X-Forwarded-For匹配
过滤器
过滤器主要有以下几个功能:
功能扩展和定制: 通过拦截和处理数据流或事件流, 可以修改数据, 增加额外的功能逻辑, 实现特点的业务需求
数据校验和过滤: 在接收到数据之后, 可以使用过滤器对数据进行检查, 严重数据的合法性, 过滤掉无效或不符合要求的数据
安全保护: 可以控制访问, 验证权限, 对输入的请求进行检查和清洗
性能优化: 可以对数据进行转换, 过滤或者缓存, 以提高处理速度和效率,. 还可以用于数据压缩, 缓存预热等场景, 减少数据传输和处理的成本
统一处理和逻辑复用: 可以在不同组件或模块上应用相同的逻辑或处理方式
内置过滤器
内置过滤器分为局部过滤器和全局过滤器
局部过滤器和全局过滤器用法相同只是一个只适用于当前匹配的服务一个适用于全局
gateway: routes: - id: user-service uri: lb://user-service-demo predicates: - Path=/user/** filters: # 局部过滤器 - AddResponseHeader=My-Resp-Header,javacn - id : order-service uri: lb://order-service-demo predicates: - Path=/order/** default-filters: # 全局过滤器 - AddResponseHeader=My-Resp-Header2,javacn2 - AddRequestHeader=My-Req, javacn
Retry
GateWay中也可以和OpenFeign一样配置重试机制
spring: application: name: gateway-service cloud: nacos: discovery: server-addr: localhost:8848 username: nacos password: nacos register-enabled: false gateway: routes: - id: user-service uri: lb://user-service-demo predicates: - Path=/user/** filters: - AddResponseHeader=My-Resp-Header,javacn - name: Retry args: retries: 3 # 重试次数 statuses: GATEWAY_TIMEOUT # 重试的 HTTP 状态代码=504 methods: GET # 重试的 HTTP 方法 series: SERVER_ERROR # 重试状态码段 5xx 状态 backoff: # 重试指数配置策略 firstBackoff: 10ms # 第一次重试间隔 maxBackoff: 50ms # 最大重试间隔 factor: 2 # firstBackoff * (factor ^ n) basedOnPreviousValue: false # 基于上次值
注意: name必须是Retry, 否则识别不了
自定义全局过滤器
Spring Cloud GateWay 中也提供了自定义全局过滤器, 我们可以通过它来实现统一认证授权等功能
package com.example.gatewayservice.filter; 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.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class AuthFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 获取request对象 ServerHttpRequest request = exchange.getRequest(); // 获取response对象 ServerHttpResponse response = exchange.getResponse(); // 获取参数 String username = request.getQueryParams().getFirst("username"); String password = request.getQueryParams().getFirst("password"); if (username != null && username.equals("admin") && password != null && password.equals("admin")) { return chain.filter(exchange); }else { // 设置无权限 401 response.setStatusCode(HttpStatus.UNAUTHORIZED); // 执行完成不在往下执行 return response.setComplete(); } } @Override public int getOrder() { // 值越小越早执行 return 1; } }