当前位置: 代码迷 >> 综合 >> Spring Cloud Zuul(API网关服务)(2)
  详细解决方案

Spring Cloud Zuul(API网关服务)(2)

热度:57   发布时间:2023-11-20 01:34:03.0

路由详情

传统路由配置

传统路由配置方式就是在不依赖与服务发现机制的情况下,通过在配置文件中具体指定每个路由表达式与服务实例的映射关系来实现API网关对外部请求的路由。

单实例配置:通过zuul.routes.<route>.path与zuul.routes.<route>.url参数对的方式进行配置进行配置,比如:

zuul.routes.api-a-url.path=/api-a-url/**
zuul.routes.api-a-url.url=http://localhost:8082/

该配置实现了对符合/api-a-url/**规则的请求路径转发到http://localhost:8082/地址的路由规则。比如

多实例配置:通过zuul.routes.<route>.path与zuul.routes.<route>.serviceId参数对的方式进行配置,比如:

zuul.routes.user-service.path=/user-service/**
zuul.routes.user-service.serviceId=user-service
ribbon.eureka.enabled=false
user-service.ribbon.listOfServers=http://localhost:8082/,http://localhost:8084/

该配置实现了对符合/user-service/**规则的请求路径转发到http://localhost:8082与http://localhost:8084两个实例地址的路由规则。由于存在多个实例,API网关在进行路由转发是需要实现负载均衡策略,于是需要Spring Cloud Ribbon的配合。

ribbon.eureka.enabled:由于zuul.routes.<route>.serviceId指定的服务名称,默认情况下Ribbon会根据服务发现机制来获取服务配置服务名对应的实例清单。但是这里没有整合Eureka之类的服务治理框架,所以要将参数设置为false,否则serviceId获取不到对应的实例的清单。user-service.ribbon.listOfServers:该参数与zuul.routes.<route>.serviceId的配置相对应,开头的user-service对应了serviceId的值,这两个参数的配置相当于在该应用内部手工维护了服务与实例的对应关系。

不论是单实例还是多实例的配置方式,都需要为每一对映射关系指定一个名称,也就是<route>,每一个<route>对应了一条路由规则。每条路由规则都需要path属性来定义个用来匹配客户端请求的路径表达式,并通过url或serviceId属性来指定请求表达式映射具体实例地址或服务名。

服务路由配置

通过服务路由配置只需要通过zuul.routes.<route>.path与zuul.routes.<route>.serviceId参数对的方式进行配置即可。

zuul.routes.user-service.path=/user-service/**
zuul.routes.user-service.serviceId=user-service

除此之外还有一种方式配置更简洁:zuul.routes.<serviceId>=<path>,其中<serviceId>用来指定路由的具体服务名,<path>用来配置匹配的请求的表达式。

zuul.routes.user-service=/user-service/**

因为默认情况下所有Eureka上的服务都被Zuul自动的创建映射关系来进行路由,这会使一些不开放的服务可能会被外部访问到。这时候我们可以使用zuul.ignored-services参数来设置一个服务名匹配表达式来定义不自动创建路由的规则。如果服务名匹配表达式那么zuul将跳过该服务不为其创建路由规则。比如:zuul.ignored-services=*的时候,zuul将对所有的服务都不自动创建路由规则。

默认情况下Zuul自动为服务创建的路由表达式会采用服务名作为前缀,比如user-service他会产生/user-service表达式来映射,但是这样的表达式规则比较单一,不利于管理。如果想通过-来分隔服务名与版本标示的话,只需要增加如下Bean即可:

    @Beanpublic PatternServiceRouteMapper serviceRouteMapper(){return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)","${version}/${name}");}

路径匹配

Zuul中,路由匹配的路径表达式采用Ant风格定义。Ant风格的路径表达式使用起来非常简单,它一共有三种通配符。

通配符 说明
匹配任意单个字符
* 匹配任意数量的字符
** 匹配任意数量的字符,支持多级目录
   

参考

URL路径 说明
/user-service/? 它可以匹配/user-service之后拼接一个任务字符路径,比如/user-service/a
/user-service/* 它可以匹配/user-service之后拼接任何任务字符路径,比如/user-service/a,/user-service/bb,但不能匹配/user-service/a/b
/user-service/** 它可以匹配/user-service之后拼接任何任务字符路径,还可以匹配多级目录/user-service/a/b

需要注意的是properties的配置无法保证有效,所以为了保证路由的优先顺序,我们需要使用yaml文件来配置。如:

zuul:routes:user-service-ext:path:/user-service/ext/**serviceId:user-service-extuser-service:path:/user-service/**serviceId:user-service

忽略表达式

通过zuul.ignored-patterns,该参数可以用来设置不希望被API网关进行路由的URL表达式。我们可以这么设置:

zuul.ignored-patterns=/**/hello/**
zuul.routes.api-a.path=/api-a/**
zuul.routes.api-a.serviceId=hello-service

可以看到被拦截了。

路由前缀

为了方便全局的为路由规则增加前缀信息,Zuul提供了zuul.prefix参数来进行设置。

zuul.prefix=/zzf

本地跳转

在Zuul实现的API网关路由功能中,还支持forward形式的服务端跳转配置。

zuul.routes.api-bb.path=/api-bb/**
zuul.routes.api-bb.url=forward:/hello

然后在API网关上需要增加一个/hello/local的接口

@RestController
public class HelloController {@RequestMapping("/hello/local")public String hello(){return "Hello";}
}

Cookie与头信息

默认情况下,Spring Cloud Zuul在请求路由时,会过滤掉HTTP请求头信息中的一些敏感信息,防止它们被传递到下游的外部服务器。默认的敏感头信息通过zuul.sensitiveHeaders参数定义,包括Cookie、Set-Cookie、Authorization三个属性。所以这会使Cookie在Zuul网关中默认不会传递,解决方法如:

1.通过设置全局参数为空来覆盖默认值,如:

zuul.sensitiveHeaders=

虽然可以实现Cookie的传递,但是破坏了默认设置的泳衣。

2.通过指定路由的参数来配置,方法有两种:

#方法一:对指定路由开启自定义敏感头
zuul.routes.<router>.customSensitiveHeaders=true
#方法二:对指定路由的敏感头设置为空
zuul.routes.<router>.sensitiveHeaders=

重定向问题

通过重定向的方式跳转到登录后的页面,此时登录后的请求结果状态码为302,请求响应头信息的Location指向了具体的服务实例,而请求头信息中的Host也指向了具体的服务实例IP地址和端口。

解决方式是:

zuul.addHostHeader=true

该参数配置,能够使得网关在进行路由转发前为请求设置Host头信息,以标示最初的服务端请求地址。

Hystrix 和 Ribbon支持

Zuul天生拥有线程隔离和断路器的自我保护功能,以及对服务调用的客户端负载均衡功能。但是当使用path与url的映射关系来配置路由规则时,对于路由转发的请求不会采用HystrixCommand来包装,所以这类路由请求没有线程隔离和断路器的保护,并且也不会有负载均衡的能力。所以在使用Zuul的时候尽量使用path和serviceId的组合来进行配置。

在使用Zuul搭建API网关的时候,可以通过Hystrix和Ribbon的参数来调整路由请求的各种超时时间等配置,比如:

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:该参数可以用来设置API网关中路由转发请求的HystrixCommand执行超时时间,单位为毫秒。当路由转发请求的命令执行时间超过该配置之后,Hystrix会将该执行命令标记为TIMEOUT并抛出异常。

ribbon.ConnectTimeout:该参数来设置路由转发请求的时候,创建请求连接的超时时间。

ribbon.ReadTimeout:该参数用来设置路由转发请求的超时时间。

如果想要关闭请求重试机制可以通过下面两个参数设置:

zuul.retryable=false
zuul.routes.<route>.retryable=false

zuul.retryable用来全局关闭重试机制。而zuul.routes.<route>.retryable=false则是指定路由关闭重试机制。

参考《Spring Cloud微服务实战》

  相关解决方案