Spring Cloud 在 Zuul 的 routing 阶段实现了几个过滤器,这些过滤器决定如何进行路由工作。
该过滤器运行后,会将 HTTP 请求全部转发到"源服务器",简单路由的配置如下:
#zuul路由配置
zuul:
routes:
#person为路由名
person:
path:/person/**
url:http://localhost:8080
该配置访问 http://localhost:9100/person/speak 会将请求转发到 http://localhost:8080/speak ,为了配置简化,可以省略 path 属性,简化配置如下:
#zuul路由配置
zuul:
routes:
#表示http://localhost:9100/person/speaks地址,路由到http://localhost:8080/speaks
person:
url:http://localhost:8080
url 的值必须以 http: 和 https: 字符串开头,否则不会触发简单路由。
简单路由使用了 HttpClient 进行转发,该过滤器会将 HttpServletRequest 的相关数据(HTTP方法,参数、请求头等)转换为 HttpClient 的请求实体,再使用 CloseableHttpClient 进行转发,为了保证性能,使用了 HttpClient 的连接池功能,因此,在使用简单路由时,可以配置 HttpClient 连接池的属性:
zuul.host.maxTotalConnections:目标主机的最大连接数,默认值 200。配置该属性,相当与调用了 PoolingHttpClientConnectionManager 的 setMaxTotal 方法。
zuul.host.maxPerRouteConnections:每个主机的初始连接数,默认值 20。配置该属性,相当与调用了PoolingHttpClientConnectionManager 的 setDefaultMaxPerRoute 方法。
跳转路由时当外部访问网关的 A 地址时,会跳转到 B 地址,处理跳转的过滤器为 SendForwardFilter,跳转路由的配置如下:
#zuul路由配置
zuul:
routes:
#路由名
testRoute:
path:/test/**
url:forward:/hello
表示访问 http://localhost:9100/test 地址时会自动跳转到 http://localhost:9100/hello 地址,注意,这个不是客户端跳转,在浏览器上是无法看到地址变化的,只能根据返回信息来验证,并且不能跨域名,只能在当前站点进行跳转,创建一个简单的 REST 服务验证跳转路由,如下:
package org.lixue.zuul;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloWorldController{
@RequestMapping(value="/hello/{name}",method=RequestMethod.GET)
publicStringhello(@PathVariable("name")Stringname){
return"hello"+name;
}
}
跳转路由实现比较简单,实际上是调用了RequestDispatcher 的 forward 方法
进行跳转。
当网关作为 Eureka 客户端注册到 Eureka 服务器时,可以通过配置 serviceId 将请求转发到集群的服务中,使用以下配置,可以执行 Ribbon 路由过滤器:
#zuul路由配置
zuul:
routes:
#表示http://localhost:9100/hello/speaks地址,路由到http://HELLOWORLD- PROVIDER/speaks,其中具体地址是通过eureka获取
hello:
path:/hello/**
# 注册在eureka的服务名
serviceId:HELLOWORLD-PROVIDER
与简单路由一样,serviceId 也可以被省略,当省略时,将会使用 routeId 作为 serviceId,简化配置如下:
#zuul路由配置
zuul:
routes:
HELLOWORLD-PROVIDER:
path:/hello/**
如果配置了 serviceId 或者 url 的配置项不是简单的路由格式(不以 http: 或 https:开头),也不是跳转路由格式(forward:开头),那么就会执行 ribbon 路由过滤器,配置如下:
#zuul路由配置
zuul:
routes:
#表示http://localhost:9100/hello/speaks地址,路由到http://HELLOWORLD-PROVIDER/speaks,其中具体地址是通过eureka获取
hello:
path:/hello/**
url:HELLOWORLD-PROVIDER
如果后端服务多达十几个的时候,每一个都这样配置也挺麻烦的,spring cloud zuul 已经帮我们做了默认配置,默认情况下,Zuul 会代理所有注册到Eureka Server的微服务,并且 Zuul 的路由规则如下:
http://ZUUL_HOST:PORT/serviceId/**
如果想让一个或多个服务被不路由,可以使用 zuul.ignoredServices 属性来配置,如果设置 ‘*’ 则表示所有服务被忽略,配置如下:
zuul:
#不被路由的serviceId,多个使用逗号分割
ignored-services:HELLOWORLD-PROVIDER
除了使用 zuul.ignoredServices 来忽略路由服务外,还可以使用 zuul.ignoredPatterns 来设置不进行路由的 Url,配置如下:
#zuul路由配置
zuul:
routes:
#表示http://localhost:9100/hello/speaks地址,路由到http://HELLOWORLD-PROVIDER/speaks,其中具体地址是通过eureka获取
hello:
path:/hello/**
#或者使用url:HELLOWORLD-PROVIDER含义一样
serviceId:HELLOWORLD-PROVIDER
ignored-patterns:/hello/noRoute
访问/hello会被路由到HELLOWORLD-PROVIDER服务,但是/hello/noRoute不会被路由。
在集群的服务间共享请求头并没有什么问题,但是如果请求会被转发到其他系统,那么对于敏感的请求头信息,就需要进行处理。在默认情况下,HTTP 请求头的 Cookie、SetCookie、Authorization 属性不会传递到"源服务",可以使用 sensitiveHeaders 属性来配置敏感请求头,下面的配置全局生效:
#zuul路由配置
zuul:
#HTTP请求头不进行转发
sensitive-headers:Cookie,Set-Cookie,Authorization
#如果只希望针对一个路由生效,可以在路由下进行配置,如下:
zuul:
routes:
#表示http://localhost:9100/hello/speaks地址,路由到http://HELLOWORLD-PROVIDER/speaks,其中具体地址是通过eureka获取
hello:
path:/hello/**
#或者使用url:HELLOWORLD-PROVIDER含义一样
serviceId:HELLOWORLD-PROVIDER
#HTTP请求头不进行转发
sensitive-headers:Cookie,Set-Cookie,Authorization
如果每一个路由都需要配置一些额外的敏感Header时,那你可以通过 zuul.ignoredHeaders
来统一设置需要忽略的HTTP请求头,默认情况下,是没有配置的,如果项目中引入了Spring Security,那么Spring Security会自动加上这个配置,默认值为: Pragma、Cache-Control、X-Frame-Options、X-Content-Type-Options、X-XSS-Protection、Expries。