Spring Cloud-Zuul服务网关
Zuul简介
Spring Cloud Zuul是Spring Cloud Netflix子项目的核心组件之一,是微服务架构中的API网关,支持动态路由与过滤功能。下面主要对其用法做详细介绍。
API网关为微服务架构提供统一访问入口,客户端通过API网关访问相关服务。它实现了请求路由、负载均衡、过滤校验、服务容错、服务聚合等功能。
创建zuul-proxy模块
在pom.xml中添加相关依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
在application.xml中进行配置:
server:
port: 8801
spring:
application:
name: zuul-proxy
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8001/eureka
在启动类添加@EnableZuulProxy注解来启用Zuul的API网关功能
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulProxyApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulProxyApplication.class, args);
}
}
启动相关服务:
eureka-server
user-service-8201
user-service-8202
feign-service
zuul-proxy
注册中心显示:
配置网关路由规则
zuul:
routes:
user-service:
path: /userService/**
feign-service:
path: /feignService/**
访问以下地址,路由至user-service服务上。
请求地址:http://localhost:8801/userService/user/list
响应结果:{"message":"操作成功","code":200,"data":[{"id":100,"username":"admin","password":"123456"}]}
访问以下地址,路由至feign-service服务。
请求地址:http://localhost:8801/feignService/user/feign/100
响应结果:{"message":"操作成功","code":200,"data":{"id":100,"username":"admin","password":"123456"}}
负载均衡
多次调用地址:
http://localhost:8801/userService/user/list
可以发现,请求日志交替在8201和8202服务上,如下所示:
[nio-8201-exec-5] c.w.s.userservice.UserServiceImpl : 查询用户列表...
[nio-8201-exec-6] c.w.s.userservice.UserServiceImpl : 查询用户列表...
[nio-8201-exec-7] c.w.s.userservice.UserServiceImpl : 查询用户列表...
[nio-8201-exec-9] c.w.s.userservice.UserServiceImpl : 查询用户列表...
配置访问前缀
通过以下配置,可以给网关路径添加统一前缀,如下所示:
zuul:
prefix: /proxy
添加/proxy统一前缀。
接口访问地址为:
http://localhost:8801/proxy/userService/user/list
Header过滤及重定向添加Host
Zuul在请求路由时,默认会过滤掉一些敏感的头信息,以下配置可以防止路由时的Cookie及Authorization的丢失:
zuul:
#配置过滤敏感的请求头信息,设置为空就不会过滤
sensitive-headers: Cookie,Set-Cookie,Authorization
Zuul在请求路由时,不会设置最初的host头信息,以下配置可以解决:
zuul:
#设置为true重定向是会添加host请求头
add-host-header: true
过滤器
路由与过滤是Zuul的两大核心功能,路由功能负责将外部请求转发到具体的实例上去,是实现统一访问入口的基础;过滤功能负责对请求进行额外的处理,是请求校验过滤及服务聚合的基础。
过滤器类型
Zuul中有以下几种典型的过滤器类型:
pre:在请求被路由到目标服务前执行,比如权限校验、打印日志等功能;
routing:在请求被路由到目标服务时执行,这是使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方;
post:在请求被路由到目标服务后执行,比如给目标服务的响应添加头信息,收集统计数据等功能;
error:请求在其他阶段发生错误时执行。
自定义过滤器
接下来我们自定义一个过滤器来演示下过滤器的作用。
添加PreLogFilter类继承ZuulFilter
@Component
public class PreLogFilter extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(ZuulFilter.class);
/**
* 过滤器类型:pre、routing、post、error四种类型
*
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器执行顺序,数值越小优先级越高
*
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否进行过滤,返回true时进行过滤
*
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 自定义的过滤器逻辑,当shouldFilter()方法返回true时执行
*
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String remoteHost = request.getRemoteHost();
String requestURI = request.getRequestURI();
String method = request.getMethod();
logger.info("Remote Host:{}, URI:{}, Method:{}", remoteHost, requestURI, method);
return null;
}
}
访问接口,可以看到过滤器打印日志如下:
[nio-8801-exec-5] com.netflix.zuul.ZuulFilter : Remote Host 0:0:1, URI:/proxy/userService/user/list, Method:GET
[nio-8801-exec-4] com.netflix.zuul.ZuulFilter : Remote Host 0:0:1, URI:/proxy/userService/user/list, Method:GET
[nio-8801-exec-6] com.netflix.zuul.ZuulFilter : Remote Host 0:0:1, URI:/proxy/userService/user/list, Method:GET
禁用过滤器
我们可以对过滤器进行禁用的配置,配置格式如下:
zuul:
filterClassName:
filter:
disable: true
Ribbon和Hystrix的支持
由于Zuul自动集成了Ribbon和Hystrix,所以Zuul天生就有负载均衡和服务容错的能力,我们可以通过Ribbon和Hystrix的配置来配置Zuul中的相应功能。
使用Hystrix的配置来设置路由转发时HystrixCommand的执行超时时间:
hystrix:
# 用于控制HystrixCommand的行为
command:
default:
execution:
isolation:
thread:
# 配置HystrixCommand执行的超时时间,执行超过该时间会进行服务降级处理
timeoutInMilliseconds: 1000
使用Ribbon的配置来设置路由转发时请求连接及处理的超时时间:
ribbon:
# 服务请求连接超时时间(毫秒)
ConnectTimeout: 1000
# 服务请求处理超时时间(毫秒)
ReadTimeout: 3000
Gitee项目源码地址:
https://gitee.com/whwtree/springcloud-learning.git
(完)