Zuul 作为网关服务,负责处理所有外部请求,并将这些请求路由到相应的服务实例。为微服务架构中的各个服务提供动态路由、监控、身份认证与安全、负载均衡等功能。
1 入门
Zuul 集合了Eureka客户端、Ribbon及Hystrix的功能。
1.1 基本配置
pom依赖:
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId></dependency>
</dependencies>
然后在Application类加上@EnableZuulProxy注解(复合注解,@EnableCircuitBreaker、@EnableDiscoveryClient)。
application.yml 配置文件如下:
server:port: 8090
spring:application:name: zuul-proxy
eureka:instance:prefer-ip-address: trueclient:service-url:defaultZone: http://localhost:8060/eureka
1.2 路由配置规则
Zuul提供了多种机制对请求路由进行映射:
- 默认机制,与Eureka服务器整合,自动根据微服务ID进行映射。例如
http://zuul服务器ip及端口/微服务1的id/user/detail?id=1
这个是请求微服务1的usr/detail接口。
- 结合微服务id通过自定义方式进行路由映射。
- 直接使用静态URL路径的方式对微服务进行路由映射。
- 添加全局路由映射。
- 通过自定义路由转化器,实现更灵活的路由映射。
1.2.1 自定义微服务访问路径
有时,我们不希望通过服务id来进行访问,而是通过自定义形式,例如,上面的请求路径,我们喜欢替换成http://zuul服务器ip及端口/service1/user/detail?id=1 将服务id替换成我们自定义的service1。配置格式如下:zuul.routes.服务id = /service1。
这是,默认访问机制仍然有效,即http://zuul服务器ip及端口/微服务1的id/user/detail?id=1 请求还是能访问到同样的资源。如果要禁止默认访问机制,则通过zuul.ignored-services=服务id 来配置,多个服务id用逗号隔开。
1.3 Header设置
客户端对Zuul发起请求及Zuul将请求转发到下游服务时,会将请求中的头部信息数据转发给下游服务,有时需要对Header的信息进行脱敏处理。
zuul.sensitiveHeaders | Zuul在请求路由时,会过滤配置的请求头。 |
zuul.ignoredHeaders | 过滤的是整个请求链路中配置的请求头,包括客户端对Zuul的请求。ignoredHeaders包含了sensitiveHeaders。 |
表 两种过滤请求头的配置
1.4 容错与回退
需要实现ZuulFallbackProvide接口,并将该类注册成bean。
@Component
public class ProviderServiceFallbackProvider implements ZuulFallbackProvider {@Overridepublic String getRoute() { // 需要提供回退功能的服务return "provider";}@Overridepublic ClientHttpResponse fallbackResponse() { // 回退响应return new ClientHttpResponse() {@Overridepublic HttpStatus getStatusCode() throws IOException {return HttpStatus.OK;}@Overridepublic int getRawStatusCode() throws IOException {return 200;}@Overridepublic String getStatusText() throws IOException {return "容错";}@Overridepublic void close() {}@Overridepublic InputStream getBody() throws IOException {return new ByteArrayInputStream("容错".getBytes());}@Overridepublic HttpHeaders getHeaders() {HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON_UTF8);return headers;}};}
}
Zuul在与Hystrix整合时其监控的颗粒度是微服务,而不是微服务中具体的某个方法。
同Hystrix一样,Zuul配置服务时间也是通过hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds属性。
Ribbon在服务执行时也有个超时时间配置,默认为5s:servicename.ribbon.ReadTimeou
2 Zuul 过滤器
过滤器的功能时负责对请求的处理过程进行干预,实现请求校验。
PRE | 在请求路由之前被调用。可用于身份验证、记录请求信息等。 |
ROUTING | 在调用目标服务之前被调用。可用于处理一些动态路由。 |
POST | 在目标微服务执行后,所返回的结果在返回给客户端时被调用。可用于添加Header、数据采集等。 |
ERROR | 在处理请求过程中发生错误时候被调用。可用于对异常、错误进行统一处理。 |
图 Zuul的4种过滤器类型
Zuul还支持自定义过滤器。
图 Zuul过滤器的声明周期
- PRE过滤器可以对请求进行监控或修改,但不可以将服务请求重新定位到不同的服务中。
- ROUTING过滤器可以将服务请求根据需要分发到不同的服务实例中,但不能执行HTTP的重定位。
@EnableZuulProxy注解包含了@EnableZuulServer的所有功能,并加入了@EnableCircuitBreaker和@EnableDiscoverClient。