099:Gateway源码深度源码分析
1 GateWay深度源码解析课程介绍
课程内容:
- GateWay的谓词有哪些
- GateWay整体执行流程
- GateWay深度源码分析
- GateWay解决跨域的问题
2 GateWay词汇表格介绍
SpringCloud Gateway常用名词
Route 路由:由路由id(唯一)、转发uri(真实服务地址)、过滤器、谓词组成;
Predicate 谓词:匹配规则;
Filter 过滤器:对下游的服务器之前和之后实现处理;
3 GateWay网关谓词用法
1 匹配时间之后
spring:
application:
name: mayikt-gateway
cloud:
gateway:
###路由策略
routes:
- id: mayikt
uri: http://www.mayikt.com/
###匹配规则
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
此路由与 2017 年 1 月 20 日 17:42 MountainTime(Denver)之后的所有请求相匹配。
2 匹配对应的host
server:
port: 80
####服务网关名称
spring:
application:
name: mayikt-gateway
cloud:
gateway:
###路由策略
routes:
- id: gateway-member
uri: lb://mayikt-member/
###匹配规则
predicates:
- Host=gateway.mayikt.com
3 根据权重比例转发(概率实现)
server:
port: 80
####服务网关名称
spring:
application:
name: mayikt-gateway
cloud:
gateway:
###路由策略
routes:
- id: weight_order
uri: lb://mayikt-order/
predicates:
- Weight=group1, 8
- id: weight_member
uri: lb://mayikt-member/
predicates:
- Weight=group1, 2
详细参考官方文档:
https://cloud.spring.io/spring-cloud-gateway/reference/html/#gateway-request-predicates-factories
4 GateWay入口配置类源码分析
工作原理图
SpringBoot项目源码的入口META-INF/spring.factories
5 GateWay核心配置类源码分析
- GatewayClassPathWarningAutoConfiguration 检查是否配置webflux依赖和是否引入spring-boot-starter-web依赖(引入报错)
- GatewayAutoConfiguration 加载Gateway需要注入的类
- GatewayLoadBalancerClientAutoConfiguration 网关需要使用的负载均衡
lb://mayikt-member/ 根据服务名称查找真实地址 - GatewayRedisAutoConfiguration 网关整合Redis整合Luau实现限流
- GatewayDiscoveryClientAutoConfiguration 服务注册与发现功能
6 GateWay路由模式底层源码分析
源码分析:
- 客户端向网关发送Http请求,会到达DispatcherHandler接受请求,匹配到RoutePredicateHandlerMapping;
- 根据RoutePredicateHandlerMapping匹配到具体的路由策略;
- FilteringWebHandler获取路由的GatewayFilter数组,创建GatewayFilterChain 处理过滤请求;
- 执行代理业务逻辑访问。
7 GateWay如何解决网关跨域的问题
微服务中跨域的问题不属于前端解决,就算前端使用jsonp也只能支持get请求,核心点在后端。
解决跨域(浏览器访问端口号和页面请求的端口号不一致)
- HttpClient转发(不靠谱)
- 使用过滤器允许接口可以跨域 响应头设置
- Jsonp不支持post请求,属于前端解决
- Nginx解决跨域的问题,保持域名和端口一致性
- Nginx也是可以通过配置文件解决跨域的问题
- 基于微服务网关解决跨域问题,需要保持域名和端口一致性
- 使用网关代码允许所有的服务可以跨域
- 使用SpringBoot注解形式@CrossOrigin
GateWay解决跨域的问题
@Component
public class CrossOriginFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
return chain.filter(exchange);
}
}
html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>网络请求</title>
</head>
<body>
<input type="button" value="网络请求" onclick="function0();" />
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function function0(){
axios.get("http://127.0.0.1/")
.then(function(response){
alert(response.data);
})
.catch(function(error){
console.log(error);
})
}
</script>
</body>
</html>
测试效果: