基于春云网关的路由实践

  

基本介绍

  

春云网关(下文以SCG代替),顾名思义这是由春官方出品的一款网关产品,是春天的云的子项目。

  
  

这个项目提供了一个API库构建一个网关alt="基于春云网关的路由实践“>
这是官方网站的工作原理示意图,从上图可以看出SCG在整个流程中主要担任反向代理的角色。客户端请求抵达SCG后,SCG通过处理程序映射将请求路由到Web处理程序,网络处理器再通过滤波器对原始请求进行处理,最终发送到被代理的服务端。

  

技术对比

  

在研究SCG之前,我们发现春云下面已经有一个成熟的API套件春云Netflix,提供了服务注册发现(尤里卡)熔断器(Hystrix)、智能路由(Zuul)和客户端负载均衡(丝带)等特性,其中就有我们需要的路由功能Zuul。
那为什么在集成一个路由功能后,春云还要自己开发一个用于路由网关的项目呢?我们来看看他们的一些对比,由于春云只集成了Zuul1.0,所以比较也集中在Zuul1.0和SCG之间。

              连接方式   支持服务器   功能               Zuul1.0   Servlet API   Tomcat,暗潮   基本路由规则,仅支持道路的路由         SCG   反应堆   网状的   较多路由规则,可以支持头,饼干,查询,方法等丰富的预测定义            

从上面的对比来看,SCG基于反应堆项目可以获得更优秀的吞吐,在功能方面相当于Zuul的优化,更加灵活的配置可以满足几乎所有的网关路由需求。
虽然说Zuul2.0也是基于网状的开发,并增强了路由和过滤器功能,然而他的多次跳票最终让春天下决心自己做一款网关路由产品,并表示不会将Zuul2.0集成进以后的春云中,也算一段趣闻吧。

  

网关实践

  

下面我们实际动手实现一个网关,结合过程中遇到的问题来熟悉SCG的各项特性。

  

初始化

  

我们新建一个基于弹簧引导的Maven项目,添加SCG的依赖,主要是下面两个

  
 <代码> & lt; dependency>
  & lt; groupId> org.springframework.cloud
  & lt; artifactId> spring-cloud-starter-gateway
  & lt;/dependency>
  & lt; dependency>
  & lt; groupId> org.springframework.boot
  & lt; artifactId> spring-boot-starter-webflux
  & lt;/dependency>  
  

这里选择的是最新的弹簧引导发布版本(2.1.4)以及支持2.1的春云分支格林威治。

  

最后建一个SpringBootApplication,参照首页的演示去掉Hystrix和RateLimit相关的内容就可以跑起来了(https://spring.io/projects/spring-cloud-gateway)。

  

动态路由

  

光有个演示肯定不行,我们的网关是要实际投产使用的,在分析了实际需求之后我们发现急需的第一个功能是动态路由。
在文档中提供了两种方式的路由配置方式

  
      <李>   

    通过java API
    直接通过RouteLocatorBuilder构建如下:

      
     <代码> builder.routes () .route (“path_route”,
      r→r.path (“/? .uri (“http://httpbin.org”)) .build();  
      李   <李>   

    通过配置文件
    通过YAML文件构建路由如下:

      
     <代码>春:
      云:
      网关:
      路线:
      - id: host_route
      uri: https://example.org
      谓词:
      -路径=/foo/{段},/酒吧/{段} 
      李   
  

但是实际需求中存在动态分配路由的场景,以上两种方式显然都不能满足需求。

  

通过查看源代码发现SCG加载路由是通过RouteDefinitionLocator接口实现,有以下默认实现(框掉的部分可以暂时忽略,这是我们自己的实现):

  

基于春云网关的路由实践“> </p>
  <p>在GatewayAutoConfiguration中通过主要的方式指定CompositeRouteDefinitionLocator作为路由定义加载的入口,通过组合模式将所有的RouteDefinitionLocator代理。最终通过CompositeRouteDefinitionLocator的getRouteDefinitions方法将所有定义加载出来。</p>
  <pre> <代码> @ bean
  @Primary
  公共RouteDefinitionLocator RouteDefinitionLocator (
  List<RouteDefinitionLocator>routeDefinitionLocators) {
  返回新CompositeRouteDefinitionLocator (
  Flux.fromIterable (routeDefinitionLocators));
  }</代码> </pre>
  <pre> <代码>公共类CompositeRouteDefinitionLocator实现RouteDefinitionLocator {
  
  私人最终Flux<RouteDefinitionLocator>代表;
  
  公共CompositeRouteDefinitionLocator (Flux<h2 class=基于春云网关的路由实践