soul 网关(十二):数据同步方式之 Http(一)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了soul 网关(十二):数据同步方式之 Http(一)相关的知识,希望对你有一定的参考价值。

参考技术A 本文主要是讲解 Http 的长轮询的概念和 Soul 上是怎么使用 Http Long Polling 的。

说到长轮询,就有不得不说轮询,以下是两者的概念:

轮询:不管服务端数据有无更新,客户端每隔定长事件请求拉去一次数据,可能有更新数据返回,也有可能什么都没有。
长轮询:客户端发起长轮询,此时如果服务端没有相应的数据,会 hold 住请求(所谓的hold住请求指的服务端暂时不回复结果,保存相关请求,不关闭请求连接,等相关数据准备好,写回客户端),直到服务端有相关数据, 或者等待一定时间超时才会返回。返回后, 客户端又会立即再次发送下一次的长轮询。

这里为什么不直到服务端有相关数据,在进行返回呢?而是可以等待一定的时间就返回呢? 这个主要的原因是网络传输层走的是 tcp 协议, tcp 所建立的连接时虚拟的,可能存在某段时间网络不通,或者服务器服务器非正常关闭等情况,客户端根本不知道服务器此时已经不能互通,还在等待着服务器发送数据过来,而这一等就要等很长的时间, 机器的操作系统层面倒是有参数可以调整,但这样比较不靠谱,所以长轮询的是线上一般都需要设置超时时间。

soul 上的官网上说它吸取了 nacos , Apollo 的设计思想,我去搜了下,有个 nacos 的 issue 上说 :

而 Soul 的大体思路如下图所示:

Soul http 长轮询机制如上所示,soul-web 网关请求 admin 的配置服务,读取超时时间为 90s,意味着网关层请求配置服务最多会等待 90s,这样便于 admin 配置服务及时响应变更数据,从而实现准实时推送。

知道了基本长轮询的基本概念,和 Soul 网关的大体实现思路,我们就可以往下分析了。

高性能网关Soul深入解析:http初体验及divide插件功能解析

Soul Http初体验

书接上回,我们run起来了Soul的控制台和网关,把基础设施搞起来了,也了解了Soul的模块,有了对Soul最初的认识。

秦老师讲过学习大型开源项目代码可以分为几个步骤,个人觉得非常值得借鉴,同时结合自己看源码的一些经验总结如下:

  • 看介绍,跑demo

  • 看入门的guide,自己写一个demo

  • 将功能集成到自己的应用中,学会如何使用基本功能并学习一些高级特性

  • 总结项目的优点与不足,加入自己的思考

  • 捋出主线,沿着主线看源码,边看边debug;大胆假设,小心求证

  • 不要纠结细节,先放眼全局

  • 修改源码,自己实现,我可以了

今天我们就使用这个思路,学习Soul的http-demo和其中涉及的相关知识点。

Run Demo

首先,我们把demo run起来,run soul-examples-http的SoulTestHttpApplication即可。

启动日志如下:

通过日志可以看出,测试应用基于netty框架,监听了8188端口。同时看到有五条http client注册成功的日志,上下文根分别是/http/test和/http/order。

通过观察目录结构,controller包下面有两个Controller,一个是HttpTestController,一个是OrderController。进入代码后发现,两个controller分别和两个上下文根相对应。

同时我们打开控制台,打开divide插件页面

高性能网关Soul深入解析(2):http初体验及divide插件功能解析

可以发现,日志里的注册成功的信息静静的躺在控制台里。我们就不禁有了第一个疑问,注册的行为是怎么发生的呢?

观察这个页面,我们发现分为两部分,一部分是selectorList,第二部分是rulesList。我理解selector是断言加路由的基本信息,用来判断请求是否走当前selector,同时还支持配置多个host用来进行负载均衡。而rulesList里面的规则则代表,在当前selector下面,什么样的url可以匹配对应接口。在请求流程中,selector可以选出host,而rule可以匹配出url,两者相加就得到了最终的调用url。

通过RestClient执行请求

GET http://localhost:9195/findById?id=sss
Accept: */*
Cache-Control: no-cache

在网关日志报错

2021-01-16 00:36:16.934 ERROR 9632 --- [-work-threads-1] o.d.soul.plugin.base.utils.CheckUtils    : can not match selector data: divide

可以看出,没有匹配到selector。因为selector定义的断言是url要匹配/http/**

我们将请求更换为以下形式

GET http://localhost:9195/http/order/findById?id=sss
Accept: */*
Cache-Control: no-cache

得到以下结果

{"id":"sss","name":"hello world findById"}

说明调用成功。

在selector界面,可以添加多条configuration。我们另外添加了一条记录(ip不存在),权重均为50.

通过多次测试,发现接近一半的几率请求调用不成功,说明负载均衡机制成功了。

观察整个页面,还有几个配置值得注意。一个是type,有两个取值,custom和full,含义为自定义或全局的意思。MatchType支持and和or两种形式,即代表多个conditions如何匹配。这个设计就比SCG要好很多,SCG就是简单粗暴的AND形式,不是很灵活,但是应用可以通过自己扩展GatewayFilter完成需求。order代表当前selector在当前plugin的所有selector中的排序,通过order可以得到一个OrderedSelectorList,保证selector按照业务需求顺序执行。

rule界面如下:

rules同样支持断言之间的逻辑操作,and和or。和selector不同的是LoadPlugins,支持3种负载均衡策略。这里的负载均衡策略应该是对应接口级别的负载均衡。



以上是关于soul 网关(十二):数据同步方式之 Http(一)的主要内容,如果未能解决你的问题,请参考以下文章

高性能网关Soul深入解析:http初体验及divide插件功能解析

Soul网关探秘divide插件原理

soul 网关(十五):限流和熔断的扫盲篇

Soul网关Hystrix插件相关知识点扫盲

Soul 学习笔记---搭建编译项目

记录一下落地网关soul(shenyu)过程中的一些实践