springcloud gateway 源码解析、请求响应流程、第三方响应结果在 gateway 的经过

大家好,我是烤鸭:

1.  官方介绍

官方文档:

看的是 2.2.5.RELEASE 版本的

https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/

看一下官方这段说明,gateway 使用的是 webflux 和 reactor,有一些同步的包(data,security 可能不支持)。

还有就是需要netty作为服务器,传统的 servlet 模型和 war 包不支持。

工作流程:

简单说就是网关收到客户端的 request 之后经过一系列请求过滤器到代理的服务,收到 response之后,再经过一系列的响应过滤器返回到网关->客户端。

2.  源码分析

2.1  reactor 介绍

由于 gateway 是基于 reactor 的,先看下 reactor 的 Flux 和 Mono

reactor 是响应式编程,相对的传统模式 遍历-> 拉取 ->TODO ,而响应式 遍历(发布) -> 订阅者 -> TODO,是基于 发布 — 订阅的模式。

而 Flux 和 Mono 是 Reactor 中的两个基本概念。都实现 CorePublisher 接口。(用于发布的元素)

Flux 表示的是包含 0 到 N 个元素的异步序列。在该序列中可以包含三种不同类型的消息通知:正常的包含元素的消息、序列结束的消息和序列出错的消息。当消息通知产生时,订阅者中对应的方法 onNext(), onComplete()和 onError()会被调用。Mono 表示的是包含 0 或者 1 个元素的异步序列。该序列中同样可以包含与 Flux 相同的三种类型的消息通知。Flux 和 Mono 之间可以进行转换。对一个 Flux 序列进行计数操作,得到的结果是一个 Mono对象。把两个 Mono 序列合并在一起,得到的是一个 Flux 对象。

2.2 handler 和 filter

看了网上一些资料,从 ReactorHttpHandlerAdapter.apply 开始,debug 看看从哪发起的。

HttpServerHandle.onStateChange 这个是监听连接状态的方法,可以看到请求刚进来的时候是 request_received

HttpWebHandlerAdapter.apply ,包装模式,request 和 response,继续执行 handle方法,生成 exchange 对象,将 request ,response 还有其他的 attribute 封装到一个对象

之后进去 Dispatcherhandler.handle ,这里边会有3个操作,获取路由(getHandler)、请求路由(invokeHandler)、解析结果(handleResult)

获取路由:AbstractHandlerMapping.getHandler (代码没贴,有个判断 是否跨域配置的判断) 中间调用RoutePredicateHandlerMapping.getHandlerInternal,从RouteLocator 获取 路由信息

请求路由:默认走的是 SimpleHandlerAdapter.handle

FilteringWebHandler.handle,获取路由对象和对应的 filter,经过 过滤器链,默认是9个全局过滤器,主要看下 NettyRoutingFilter 和 NettyWriteResponseFilter

NettyRoutingFilter.filter 就是发送http请求,调用第三方服务,对response 请求头过滤处理,将response 封装到 Mono

NettyWriteResponseFilter.filter

可以看出来这时候netty 已经响应结果,并且往 exchange的reponse 写入

会判断响应的 content-type 是流还是其他的,如果是流的话,写入并刷新。这个地方看一下 wrap 方法,我找了半天都没有找到 gateway 在哪保存的第三方服务的返回值,就在这个byteBuf,封装 DataBuffer,设置到 DataBufferFactory,和 response 绑定。

看一下 wrap 方法

之后的方法调用 ReactorServerHttpResponse.writeWithInternal ,感兴趣可以看出,代码就不贴了。

由于 SimpleHandlerAdapter 返回的是 `Mono.empty()` ,所以不会触发 handleResult 方法。

其中还有HttpServerHandle.onStateChange 监听到其他的状态,也不贴了。

3.  总结

以上就是 gateway 收到请求后,到返回一系列的流程,内容也不是特别全。

监听到请求进入:HttpServerHandle.onStateChange(newState = request_received) ->

包装 request和response:ReactorHttpHandlerAdapter.apply ->

生成 exchange(包含 request和 response),用于netty请求 : HttpWebHandlerAdapter.apply ->

获取路由、请求路由、解析结果:Dispatcherhandler.handle ->

获取路由 AbstractHandlerMapping.getHandler:-> RoutePredicateHandlerMapping.getHandlerInternal

请求路由:SimpleHandlerAdapter.handle:-> FilteringWebHandler.handle

默认9个全局过滤器:

发送http请求,调用第三方服务,对response 请求头过滤处理,将response 封装到 Mono:NettyRoutingFilter.filter

获取netty 响应结果,并且往 exchange的reponse 写入:NettyWriteResponseFilter.filter

结果解析:ResponseBodyResultHandler.handleResult (由于 SimpleHandlerAdapter 返回的是 Mono.empty(),所以不会触发 handleResult 方法)

写入response并返回:NettyWriteResponseFilter.wrap (byteBuf,封装 DataBuffer,设置到 DataBufferFactory,和 response 绑定)

 

所以看到有一些想在网关层面修改 response 的需求,只需要增加一个filter 修改 response绑定的 DataBufferFactory 中的 DataBuffer 即可。

 

还有一些不错的文章推荐:

https://developer.ibm.com/zh/articles/j-cn-with-reactor-response-encode/

https://blog.csdn.net/chengqiuming/article/details/103394337

https://www.jianshu.com/p/c40a757fad01

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

beetl的使用感受

beetl 的用法&#xff0c;跟layui的laytpl的模版语言差不多。写的很舒服。没有thymeleaf那么麻烦。例如 <%for(loadDischargItem in loadDischargItemList){ %><tr><td>${loadDischargItemLP.index}</td><td><input type"text" id&…

[css] css3的:nth-child和:nth-of-type的区别是什么?

[css] css3的:nth-child和:nth-of-type的区别是什么&#xff1f; :nth-child(n) 选择器匹配属于其父元素的第 N 个子元素&#xff0c;不论元素的类型。 :nth-of-type(n) 选择器匹配属于父元素的特定类型的第 N 个子元素。 n 可以是数字、关键词或公式。个人简介 我是歌谣&…

改logback logstash-logback-encoder 框架本身的日志级别

大家好&#xff0c;我是烤鸭&#xff1a; 最近遇到一个问题&#xff0c;想把logback框架本身的日志级别修改&#xff0c;需要 logstash-logback-encoder 6.1 以上的版本才可以。 直接上代码 这里修改的不是业务日志级别&#xff0c;是 logback 框架本身(确切地说是 logstash…

idea首次创建新模块的详细操作

依赖网址:https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api/3.1.0 https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api/2.3.1 https://mvnrepository.com/artifact/org.springframework/spring-webmvc 创建文件夹 修改版本号 配…

[css] 怎么使用自定义字体?有什么注意事项?

[css] 怎么使用自定义字体&#xff1f;有什么注意事项&#xff1f; font-face { font-family: 自定义字体名称; src: url(字体文件名.eot); /* IE9 Compat Modes / src: url(字体文件名.eot?#iefix) format(embedded-opentype), / IE6-IE8 / url(字体文件名.woff) format(wof…

markdown 常用语法总结 - 个人版

这里并不是要总结所有的 markdown 语法&#xff0c;只是总结笔者自己撰写博客时常用的一些 markdown 语法。 1 图片设置 1.1 设置图片位置 利用markdown在编写文档时插入图片是默认靠左&#xff0c;有些时候将图片设置为居中时可以更加的美观&#xff0c;这时就需要在图片的信息…

[css] 要是position跟display、overflow、float这些特性相互叠加后会怎么样?

[css] 要是position跟display、overflow、float这些特性相互叠加后会怎么样&#xff1f; display:none之后别的样式设置成什么都不管用了&#xff0c;dom元素不可见了。position:absolute之后float应该就不起作用了个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识…

logback AbstractLogstashTcpSocketAppender 源码解析

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享下 logback 源码 &#xff0c;版本是 6.5-SNAPSHOT。 写这篇的目的 由于最近项目中一直出现这个日志&#xff0c;而且基本每20秒就会打印一次&#xff0c;也没法关掉&#xff0c;百度上资料也很少&#xff0c;只能自己来了。 …

PostgreSQL 、springboot 、spring data jpa 集成

项目地址&#xff1a;https://gitee.com/zhxs_code/PostgreSQL_springboot_jpa_demo.git 增删查改都已经实现。 重点部分&#xff1a; 1.定义自己的方言。 1 package com.zxl.postgrespringdemo.config.dialect;2 3 import org.hibernate.dialect.PostgreSQL94Dialect;4 import…

[css] 有用过Flex吗?简要说下你对它的了解

[css] 有用过Flex吗&#xff1f;简要说下你对它的了解 给我感触最深的只有两点方便/好用子元素超出的bug关于bug, 大家有什么好的解决方案, 除了overflow: hidden个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大…

RedisTemplate value序列化导致的问题

大家好&#xff0c;我是烤鸭&#xff1a; ​ 今天分享一个redisTemplate 使用时&#xff0c;value 序列化的问题。 1. 问题描述 其实我最开始遇到的问题是&#xff1a; stringRedisTemplate.opsForSet().isMember(key,value)一直返回false问题&#xff0c;下边博客给出了…

41、OrthoMCL和mcl软件进行基因家族分析

转载&#xff1a;http://www.realbio.cn/news/124.html https://blog.csdn.net/seallama/article/details/43820763 http://www.cnblogs.com/huangying78/p/8638506.html 1. 数据库的配置 OrthoMCL的分析需要先行建立mysql账户并建立相应的数据库。关于mysql用户的创建我们不在…

[css] 如何实现换肤功能?

[css] 如何实现换肤功能&#xff1f; css 换肤常见方案 是通过 less/sass/postcss 等css 预处理器&#xff0c;通过它们自身的变量用法&#xff0c;设置不同变量&#xff0c;生成不同的主题样式&#xff0c;但是这些样式都是会被打包成常量&#xff0c;我们只能在编译之前修改…

beego——模板处理

beego的模板处理引擎采用的是Go内置的html/template包进行处理&#xff0c;而且beego的模板处理逻辑是采用了缓存编译方式&#xff0c; 也就是所有的模板会在beego应用启动的时候全部编译然后缓存在map里面。 1.模板目录 beego中默认的模板目录是views&#xff0c;用户可以把模…

日志 中文乱码、nacos 中文乱码、saltstack 中文乱码、docker中文乱码

大家好&#xff0c;我是烤鸭&#xff1a; ​ 今天分享一个 saltstack 中文乱码 的问题。 问题说明 由于项目之前没有接入公司的发布系统&#xff0c;今天接入之后发现日志乱码&#xff0c;不仅如此&#xff0c;从nacos获取到的中文参数也是乱码。于是猜想是发布系统遗留了一…

[css] 列举CSS优化、提高性能的方法

[css] 列举CSS优化、提高性能的方法 加载性能压缩CSS通过link方式加载&#xff0c;而不是import复合属性其实分开写&#xff0c;执行效率更高&#xff0c;因为CSS最终也还是要去解析如 margin-left: left;选择器性能尽量少的使用嵌套&#xff0c;可以采用BEM的方式来解决命名冲…

[css] 假如设计稿使用了非标准的字体,你该如何去实现它?

[css] 假如设计稿使用了非标准的字体&#xff0c;你该如何去实现它&#xff1f; 协商解决, 如果是重要信息, 如logo等, 使用图片, iconfont.个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 …

redis出现过多command 慢查询slowlog出现command命令

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享一个问题&#xff0c;一个关于redis slowlog&#xff0c;执行过多 command命令的问题。 问题来源 所有走redis 的接口tp99和平均耗时是原来的两倍不止&#xff0c;运维说redis 的qps也翻倍了。查了下slowlog&#xff0c;发现…

[学习笔记]上下界网络流

有的时候&#xff0c;网络流建模要考虑某些边必须选择若干次&#xff0c;又不能多于若干次&#xff0c;而且不太容易转化成比较好的限制模型&#xff0c; 就简单粗暴地给每条边定一个流量的上下界&#xff0c;求在满足上下界的基础上的一些问题。 大概有以下几种。 基本思路都是…

[css] 你知道全屏滚动的原理是什么吗?它用到了CSS的哪些属性?

[css] 你知道全屏滚动的原理是什么吗&#xff1f;它用到了CSS的哪些属性&#xff1f; 全屏滚动和轮播图类似&#xff0c;都是通过改变元素位置或者显示与隐藏来实现&#xff0c;配合JS的一些交互距离判断&#xff0c;实现类似原生滚动捕获的效果。这里全屏的话就需要将宽高都设…