网关系列之一:浅析SpringCloudGateway负载均衡实现

七月 23, 2025 / 1900 / 8阅读 / 0评论/ 分类: 软件技术

前言

心血来潮准备写一个网关项目,同时写一些文档心得来提升自己。几年前接触过api网关项目,当时感觉通过SCG改造得比较粗糙,但总的来说通过SCG网关比较符合我现在的想法:解决一些负载均衡、权限控制及静态资源解析等问题就能得到一个类似Nginx的轮子。

调试负载均衡

首先从配置文件定义一条负载均衡的路由,类似如下:

spring:
  cloud:
    discovery:
      client:
        simple:
          instances:
            test-service:
              - uri: http://localhost:8081
              - uri: http://localhost:8083
    gateway:
      routes:
        - id: route1
          uri: lb://test-service
          predicates:
            - YiFu=true,default

这里自定义了一个YIFU的路由断言工厂,让请求包进入该条路由,同时向负载均衡器提供了两个下游服务8081、8083。

DispatcherHandler 和SpringMVC一样可以看作一个比较底层入口的调度者,经过调试发现它先调用了RouterFunctionMapping组件,这个组件代理routeFunction 默认为空,直接返回,接着调用 RequestMappingHandlerMapping ,这个应该对应WebFlux的Controller中的@RequestMapping注解的入口处理,然后调用到 RoutePredicateHandlerMapping 路由断言处理,这里应该是路由代理的入口。

图片

在启动服务时,RoutePredicateHandlerMapping默认注入,有关路由的FilteringWebHandler,及路由对象,请求达到时,根据路由进行断言,从而进入路由的代理过程

图片


其中,FilteringWebHandler 中代理了11个Filter ,其中就包含了实现负载均衡的重要组件:ReactiveLoadBalancerClientFilter图片

路由到ReactiveLoadBalancerClientFilter时,首先URI判定是否需要负载均衡, 如果不需要直接跳过Filter,如果需要负载均衡,会通过LoadBalancerClientFactory来初始化以serviceId为名的应用上下文,以此扫描出配Configuration配置来实例化负载均衡器,如下图,第一次从LoadBalancerClientFactory getInstances 方法初始化上下文并实例化相关Bean

图片

其中 实例化默认的负载均衡的组件为RoundRobinLoadBalancer

图片

通过RoundRobinLoadBalancer注入的 serviceInstanceListSingletonSupplier 来获取下游服务实例,可以看到这个supplier由DiscoveryClientServiceInstanceListSupplierCachingServiceInstanceListSupplier包裹,从而具备缓存服务实例的功能。

图片

当缓存中没有实例,则通过DiscoveryClientServiceInstanceListSupplierget 获取

图片

DiscoveryClientServiceInstanceListSupplier最终引用了SimpleReactiveDiscoveryClient来获取实例。

图片


总结

通过上面的负载均衡分析,学习到了一些spring的启动加载顺序,上下文初始化,懒加载,看似很简单的一块功能,放在我面前肯定不会考虑这么多,总结出下的负载均衡过程下图:

图片

下一篇试着自定义实现下这个过程,将服务实例发现动态化管理。

 


文章作者:1900

文章链接:https://zhuty.cn/archives/gateway1

版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!


评论