一、概述
网关是我们服务的守门神,是所有微服务的统一入口,一切请求都要先到网关,再到微服务,它可以帮助我们统一的进行一种操作,处理一些问题。
网关的核心功能特性:
1.请求路由、负载均衡
一切请求都必须先经过gateway网关,但网关不处理业务,而是根据某种规则把请求转发到某个微服务,这个过程叫做路由。当然路由的目标服务同时部署多个时,还需要做负载均衡,也就是根据规则具体转发到某个服务。
2.身份认证和权限校验
网关作为微服务的入口,需要校验用户是否有请求资格,如果没有则进行拦截。
3.请求限流
当请求流量过高时,在网关中安装下流的微服务能够接受的速度来放行请求,避免服务压力过大。
4.跨域处理
我们可以在网关中统一处理跨域问题,而不必单独在每个项目中处理。
二、使用
1.创建gateway微服务
2.引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
3.编写启动类
package com.spepc.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author qx
* @date 2023/10/18
* @des 启动类
*/
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
4.在application.yml文件基础配置和路由规则
server:
# 网关端口
port: 10010
spring:
application:
# 微服务名称
name: gateway-service
cloud:
nacos:
discovery:
# nacos地址
server-addr: 127.0.0.1:8848
gateway:
# 网关配置
routes:
# 路由ID 自定义 需要唯一
- id: user-service
# 路由目标地址 lb是指负载均衡 后面是微服务名称user-service
uri: lb://user-service
# 路由断言 判断请求是否符合路由规则的条件
predicates:
# 这个是路径匹配规则 只要符合/user/开头的请求都符合要求
- Path=/user/**
main:
web-application-type: reactive
路由配置包含:
路由ID:路由的唯一标识
路由目标uri:路由的目标地址,http代表固定地址,lb代表根据服务负载均衡
路由断言predicates:判断路由的规则
路由过滤器filters:对请求或响应做处理
本例中,我们将 /user/**开头的请求,代理到lb://userservice ,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。
user模块中的微服务方法具体如下所示:
5.测试
我们启动网关服务,访问http://localhost:10010/user时,符合/user/** 规则,请求转发到uri:http://userservice/user,得到了结果:
我们访问http://localhost:10010/order时,不符合/user/** 规则,请求被拦截,得到了结果:
三、断言工厂
断言工厂的配置在SpringCloudGateway中有下列所示:
名称 | 说明 |
After | 是某个时间点后的请求 |
Before | 是某个时间点之前的请求 |
Between | 是某两个时间点之间的请求 |
Cookie | 请求必须包含某些cookie |
Header | 请求必须包含某些header |
Host | 请求必须是访问某个host域名 |
Method | 请求方法必须是指定方式 |
Path | 请求路径必须符合指定规则 |
Query | 请求参数必须包含指定参数 |
RemoteAddr | 请求者的ip必须是指定范围 |
Weight | 权重处理 |
我们只需要掌握Path这种路由工程就可以了。
四、过滤器
GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理:
自定义全局过滤器
package com.spepc.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author qx
* @date 2023/10/18
* @des 自定义全局拦截器
*/
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 获取请求参数
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
// 获取authorization参数
String authorization = params.getFirst("authorization");
if ("admin".equals(authorization)) {
// 放行
return chain.filter(exchange);
}
// 禁止访问 设置状态码
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
}
我们重启网关服务,再次访问http://localhost:10010/user发现没有请求到支持的服务数据。
我们访问http://localhost:10010/user?authorizatinotallow=admin正常访问到了数据
可以看到我们自定义的过滤器逻辑已经成功的产生了效果。
五、解决跨域问题
浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题。
解决方案:我们可以在网关服务的application.yml文件中添加下面配置:
server:
# 网关端口
port: 10010
spring:
application:
# 微服务名称
name: gateway-service
cloud:
nacos:
discovery:
# nacos地址
server-addr: 127.0.0.1:8848
gateway:
# 跨域配置
globalcors:
add-to-simple-url-handler-mapping: true
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:9001"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期
# 网关配置
routes:
# 路由ID 自定义 需要唯一
- id: user-service
# 路由目标地址 lb是指负载均衡 后面是微服务名称user-service
uri: lb://user-service
# 路由断言 判断请求是否符合路由规则的条件
predicates:
# 这个是路径匹配规则 只要符合/user/开头的请求都符合要求
- Path=/user/**
main:
web-application-type: reactive