Spring Cloud-16-Zuul网关配置详解

上文中初步使用了Zuul的路由和请求过滤,接下来就详细的看一下Zuul的路由配置

路由配置

上文中,我们配置的一个路由规则是这样的:

1
2
3
4
5
zuul:
routes:
api-a:
path: /api-a/**
serviceId: feign-consumer

要指定一个path和一个serviceId,这里可以简化一下,如下:

1
2
3
zuul:
routes:
feign-consumer: /api-a/**

zuul.routes后面是服务名,值是路径,上面这两种配置的方式都是可以的,只是下面这样写更简洁

默认配置

如果我们不去配置映射规则的话,Zuul就会设置成默认的规则,默认配置是这样的:

1
2
zuul.routes.feign-consumer.path=/feign-consumer/**
zuul.routes.feign-consumer.serviceId=feign-consumer

写成yml格式的话就是:

1
2
3
zuul:
routes:
feign-consumer: /feign-consumer/**

默认的路径就是/服务名/**

通配符详解

我们上面设置路径,最后都是两个*作为通配符,Zuul中的路由匹配规则使用了Ant风格定义,一共有三种不同的通配符:

  • ?: 可以匹配单个字符,比如路径是/api/?,就可以匹配到/api/a,/api/b
  • *: 匹配任意数量的字符,比如路径是/api/*,就能匹配到/api/aa,/api/bb等,但是只能匹配一级,像/api/aa/bb这样的路径就匹配不到了
  • **: 匹配任意数量的字符,比如路径是/api/**,就能匹配到/api/aa,/api/aa/b

指定的服务不创建路由规则

默认情况下,Zuul会为Eureka上所有注册的服务都创建映射关系, 这里就会出现一个问题, 在我们现在这个demo中,eureka-client作为服务提供者,他只是给项目中的消费者提供服务,但是默认的Zuul也会给他创建映射规则,这时候我们可以采用以下配置来跳过该服务,不创建路由规则:

1
2
zuul:
ignored-services: eureka-client

指定的接口不创建路由规则

上面的配置可以忽略掉某一个服务,不给这个服务创建映射规则,这个配置也可以进一步细化,比如说不想给/hello接口创建路由规则,那么就可以按下面这样去配置:

1
2
zuul: 
ignored-patterns: /**/hello/**

配置完成以后,可以去启动项目测试一下,访问hello接口试一下:
image
报404,说明配置生效了

接口地址重合

比如我们有两个服务一个叫feign-consumerfeign-consumer-hello,配置都路由规则假如在application.properties是这样的

1
2
3
4
5
zuul.routes.feign-consumer.path=/feign-consumer/**
zuul.routes.feign-consumer.serviceId=feign-consumer

zuul.routes.feign-consumer-hello.path=/feign-consumer/hello/**
zuul.routes.feign-consumer-hello.serviceId=feign-consumer-hello

这时,访问feign-consumer-hello的路径就会被这两条规则都匹配了,Zuul中的路径匹配方式是一种线性匹配方式,即按照路由匹配规则的存储顺序依次匹配,所以我们得确保feign-consumer-hello的匹配规则先于feign-consumer 被定义,但是在properties文件中是不能保证先后顺序的,所以就必须使用yml的配置方式,在yml中的配置如下:

1
2
3
4
5
6
7
8
zuul:
routes:
feign-consumer-hello:
path: /feign-consumer/hello/**
serviceId: feign-consumer-hello
feign-consumer:
path: /feign-consumer/**
serviceId: feign-consumer

这样就可以确保先加载的是feign-consumer-hello的匹配规则.

路由前缀

为所有路由规则增加前缀,配置如下:

1
2
zuul:
prefix: /myapi

比如配置之前访问路径是http://localhost:2006/api-a/hello1?login=1,配置了前缀之后,访问路径就变成了http://localhost:2006/myapi/api-a/hello1?login=1.

重启项目测试一下,访问原路径就会404
image

再访问加上前缀的路径:
image

网关项目中增加业务逻辑

正常来说,API网关只是作为系统的统一入口,但是有些时候我们要在网关上做一点业务逻辑,比如在api-gateway项目中新建如下Controller:

1
2
3
4
5
6
7
8
@RestController
public class TestController {

@GetMapping("local")
public String local(){
return "Zuul Local";
}
}

这时,我们希望用户访问/local接口的时候,就跳到上面这个controller中,那么就需要配置Zuul的本地跳转,如下:

1
2
3
4
5
zuul: 
routes:
local:
path: /local/**
url: forward:/local

配置好之后,访问http://localhost:2006/myapi/local,结果如下:
image
这里还有一个要注意的, 我们上篇文章中写过一个过滤器,但是走这个接口的时候是没有经过过滤器的

设置请求Host头信息

我们在使用nginx的时候,会涉及到一个请求头信息的配置,防止页面重定向后跳转到上游服务器上去,zuul中也存在相同的问题,比如说,我的feign-consumer中提供了一个/hello4的接口,当访问/hello4的时候,页面重定向到/hello,在默认情况下,重定向的地址是具体的服务实例的地址,而不是API网关的跳转地址,这样就会暴露真实的服务地址,所以需要在zuul中做如下配置,表示API网关在进行请求路由转发之前为请求设置Host头信息.

1
2
zuul:
add-host-header: true

默认情况下,敏感的头信息无法经过API网关进行传递,我们可以通过如下配置使之可以传递:

1
2
3
4
zuul:
routes:
feign-consumer:
sensitiveHeaders:

关闭重试机制

在Zuul中,Ribbon和Hystrix的配置还是和之前一样的, 如果想关闭Hystrix的重试机制可以通过下面的配置:

关闭全局重试机制:

1
2
zuul:
retryable: false

关闭某一个服务的重试机制:

1
2
3
4
zuul:
routes:
feign-consumer:
retryable: false