配置
SpringCloud Gateway使用Netty作为网络框架,Netty使用Reactor作为线程模型,采用的是事件驱动的方式。
GW默认配置是Boss线程和work线程一体,即一个线程是Boss线程的同时也是一个work线程,由于这个特性可能导致服务器本身配置不高从而导致QPS上不去,这个时候可以适当的调整线程配置,使Boss线程和work线程分离。
Reactor-Netty 默认配置如下
😅 😅 比较有意思的是,如果不去看Reactor-Netty的文档,就不知道有这个参数的存在,一开始我以为是Gateway提供的参数,结果一通查找下来发现根本没有
找了几个小时,最后想到用Netty总得使用 ServerBootStrap
进行初始化吧,这才找到它初始化的上下文,然后又根据它的上下文找到了这些参数。最终知识还是连贯起来了,不然我可能还得找几个小时。 😅 😅
有意思的点
这里涉及的异步也很有意思
- 虽然Netty本身是异步的,基于Netty的Reactor也是异步的,我们的GlobalFilter,GatewayFilter都是跑在worker线程上边的,如果这里阻塞了那么整个Gateway就阻塞在这里了
- Webflux 提供的Mono和Flow是不是异步的呢,由于对这里研究不深入,给我的感觉它这里并不是异步的,就是一个传统的生产,订阅和消费的过程。
基于上述的了解,我又去了解了异步发生哪里,最终找到了一个解释,比如线程A通过Netty的writeAndFlush调用后端Http服务是异步,write完了以后,线程A继续执行自己的任务,当Http响应的数据返回,Channel有数据可读的时候,channel对应的线程又把它读取出来响应给前端。 大致上的一个体验,我目前只感受到了这里的异步。
另外一个值得注意的是,Netty的Channel和线程之间的关系,这里存在两个双向的管理关系,假设A是客户端请求,B是Gateway,C是后端服务
以下结论为wireshark抓包得知,未深入源码进行探索
A—->B 默认是Http短链接,也就是每次都会建立Tcp链接,这就可能导致每次他都是在不同的work线程进行处理。
B—->C 则是长链接,对应的Channel会绑定到一个线程上,从输出的线程信息来看也是如此。