内容简介
Zuul 网关的功能和工作机制, 结合代码介绍如何使用 Zuul 构建一个简单的网关, 介绍 Zuul 的路由配置方式, 了解 Filter 工作原理并实现一些扩展功能.
Zuul 网关简介
Zuul 是 Spring Cloud 全家桶中的微服务 API 网关.
所有从设备或网站来的请求都会经过 Zuul 到达后端的 Netflix 应用程序. 作为一个边界性质的应用程序, Zuul 提供了动态路由, 监控, 弹性负载和安全功能. Zuul 底层利用各种 filter 实现如下功能:
认证和安全 识别每个需要认证的资源, 拒绝不符合要求的请求.
性能监测 在服务边界追踪并统计数据, 提供精确的生产视图.
动态路由 根据需要将请求动态路由到后端集群.
压力测试 逐渐增加对集群的流量以了解其性能.
负载卸载 预先为每种类型的请求分配容量, 当请求超过容量时自动丢弃.
静态资源处理 直接在边界返回某些响应.
编写一个 Zuul 网关
1, 新建一个 zuul-demo 模块, 在依赖项处添加 [Cloud Discovery->Eureka Discovery 和 Cloud Rouing->Zuul] .
2, 修改入口类, 增加 EnableZuulProxy 注解
- @SpringBootApplication
- @EnableZuulProxy
- public class ZuulDemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(ZuulDemoApplication .class, args);
- }
- }
修改 appliation.YAML
- server:
- port: 7000
- spring:
- application:
- name: zuul-demo
- eureka:
- client:
- service-url:
- defaultZone: http://localhost:7001/eureka/
- instance:
- prefer-ip-address: true
- #将 IP 注册到 Eureka Server 上, 而如果不配置就是机器的主机名.
4, 启动 Eureka Server,orderservice 和 Zuul-Demo, 在浏览器中输入 http://localhost:7000/orderservice/order/pay 获取返回结果.
从上面的例子中的地址可以看出来默认 Zuul 的路由方式是: http://ZUULHOST:ZUULPORT/serviceId/**.
如果启动多个 orderservice 可以发现 Zuul 里面还内置了 Ribbon 的负载均衡功能.
Filter 工作原理
Zuul 中的 Filter
Zuul 是围绕一系列 Filter 展开的, 这些 Filter 在整个 HTTP 请求过程中执行一连串的操作.
Zuul Filter 有以下几个特征:
Type: 用以表示路由过程中的阶段 (内置包含 PRE,ROUTING,POST 和 ERROR)
Execution Order: 表示相同 Type 的 Filter 的执行顺序
Criteria: 执行条件
Action: 执行体
Zuul 请求生命周期
一图胜千言, 下面通过官方的一张图来了解 Zuul 请求的生命周期.
image.PNG
自定义一个 Filter 实现 token 验证
添加一个 AuthZuulFilter
- public class AuthZuulFilter extends ZuulFilter {
- // 日志输出器
- private final static Logger LOGGER = LoggerFactory.getLogger(AuthZuulFilter.class);
- @Value("${server.port}")
- private String serverPort;
- // 四种类型: pre,routing,error,post
- @Override
- public String filterType() {
- return FilterConstants.PRE_TYPE;
- }
- // 自定义过滤器执行的顺序, 数值越大越靠后执行, 越小就越先执行
- @Override
- public int filterOrder() {
- return FilterConstants.PRE_DECORATION_FILTER_ORDER;
- }
- // 控制过滤器生效不生效, 可以在里面写一串逻辑来控制
- @Override
- public boolean shouldFilter() {
- return true;
- }
- // 执行过滤逻辑
- @Override
- public Object run() throws ZuulException {
- RequestContext ctx = RequestContext.getCurrentContext();
- HttpServletRequest request = ctx.getRequest();
- // 从请求头中获取 token 信息
- String userToken = request.getHeader("userToken");
- LOGGER.debug("网关端口:" + serverPort);
- if (StringUtils.isEmpty(userToken)) {
- // 设置为 false 就不会继续执行服务代码
- ctx.setSendZuulResponse(false);
- // 设置状态码
- ctx.setResponseStatusCode(401);
- // 设置相应信息
- ctx.setResponseBody("userToken is null");
- return null;
- }
- return null;
- }
- }
修改启动程序, 添加 Filter 注入:
- @Bean
- public AuthZuulFilter authZuulFilter() {
- AuthZuulFilter filter = new AuthZuulFilter();
- return filter;
- }
路由配置
Zuul 提供了一套简单且强大路由配置策略, 利用路由配置我们可以完成对微服务和 URL 更精确的控制
重写指定微服务的访问路径:
- zuul:
- routes:
- REST-demo: /REST/**
这表示将 REST-demo 微服务的地址映射到 / REST/** 路径.
忽略指定微服务:
- zuul:
- ignored-services: REST-demo,xxx-service
使用 "*" 可忽略所有微服务, 多个指定微服务以半角逗号分隔.
3, 忽略所有微服务, 只路由指定微服务:
- zuul:
- ignored-services: *
- routes:
- REST-demo: /REST/**
4, 路由别名:
- zuul:
- routes:
- route-name: #路由别名, 无其他意义, 与例 1 效果一致
- service-id: REST-demo
- path: /REST/**
5, 指定 path 和 URL
- zuul:
- routes:
- route-name:
- url: http://localhost:8000/
- path: /REST/**
此例将 http://ZUULHOST:ZUULPORT/REST / 映射到 http://localhost:8000/, 同时由于并非用 service-id 定位服务, 所以也无法使用负载均衡功能.
注意点:
cookie 处理
zuul:
sensitive-headers: cookie,header 之类额东西
#sensitive-headers 表示要被过滤的头, 黑名单, 为空则可放行所有请求头.
来源: http://www.jianshu.com/p/de04d0eeb78a