一、Zuul简介
Zuul 是 Netflix 开源的微服务网关,它可以和 Eureka、Ribbon、Hystrix 等组件配合使用,支持动态路由与过滤功能。Zuul 其实相当于是设备(手机APP)应用的 Web 网站后端所有请求的门户。
Zuul 的核心是一系列的过滤器,这些过滤器可以完成以下功能:
-
身份验证与安全:识别每个资源的验证要求,并拒绝那些与要求不符合的请求。
-
洞察力和监控:追踪有意义的数据和统计结果,以便为我们提供精确的生产视图。
-
压力测试:逐渐增加群集流量以衡量性能。
-
动态路由:根据需要动态路由请求到不同的后端群集。
-
负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求。
-
静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部群集。
-
多区域弹性:跨域AWS Region进行请求路由,以便扩大我们的ELB(Elastic Load Balancing)使用范围。
二、路由(Router)
1)创建gradle模块zuul-service并添加如下依赖
dependencies { compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client', version: '2.1.5.RELEASE' compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-zuul' }
2)在启动类上添加@EnableZuulProxy注解,标记开启Zuul代理功能。
package org.wesson.springcloud.zuul; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @EnableZuulProxy @SpringBootApplication public class ZuulServiceApplication { public static void main(String[] args) { SpringApplication.run(ZuulServiceApplication.class, args); } }
从@EnableZuulProxy注解源码中能够看出,该注解其实是一个复合注解。包含@EnableCircuitBreaker和@EnableDiscoveryClient两个注解。当启动类添加了@EnableZuulProxy注解时,就自动为该应用增加服务熔断保护功能。同时也将@EnableZuulProxy注解作为一个服务实例注册到服务治理体系中去。所以,启动类不需要再添加这两个注解了。
server: port: 8080 spring: application: name: zuul-service zuul: routes: provider: path: /provider-service/** url: http://localhost:8081/ serviceId: PROVIDER-SERVICE
zuul.routes下的属性:
-
id:自定义网关路由ID
-
path:动态路由映射路径规则
-
url:
-
serviceId:映射到此路由的服务ID
4)测试
Step1:运行 eureka-server 启动类,端口为8761
Step2:运行 provider-service 启动类,端口为8081
Step3:运行 zuul-service 启动类,端口为8080
Step4:访问http://localhost:8761/,注册到的服务如下图:
Step5:访问http://localhost:8080/provider-service/client/info,可以发现请求路由到了 provider-service 服务上了:
1)请求生命周期
2)token身份验证
package org.wesson.springcloud.zuul.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /* * CustomZuulFilter:可以实现自定义的过滤器 * @Component:交给Spring容器管理,进行组件扫描 */ @Component public class CustomZuulFilter extends ZuulFilter { /** *功能描述:定义过滤器的类型,Zuul 默认定义4种生命周期的过滤器类型: * - pre:转发到微服务之前执行的过滤器 * - routing:在路由请求时执行的过滤器 * - post:在执行微服务获取返回值之后执行的过滤器(routing、error) * - error:在整个阶段抛出异常的时候执行的过滤器 */ @Override public String filterType() { return "pre"; } /** *功能描述:指定过滤器的执行顺序 * 返回值越小,执行顺序越高 */ @Override public int filterOrder() { return 1; } /** *功能描述:判断当前过滤器是否生效 * true:将最终调用run()方法 * false:将不会调用run()方法 */ @Override public boolean shouldFilter() { return true; } /** *功能描述:执行过滤器中的业务逻辑 */ @Override public Object run() throws ZuulException { // 获取Zuul提供的上下文对象RequestContext RequestContext ctx = RequestContext.getCurrentContext(); // 获取request请求 HttpServletRequest request = ctx.getRequest(); // 通过request获取参数access-token String token = request.getParameter("access-token"); // 所有的请求需要携带一个参数:access-token // 判断token是否为空 if (token == null) { // token == null:拦截请求,返回认证失败 ctx.setSendZuulResponse(false); // 拦截Zuul网关请求 ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); // 未经过认证的错误 } // token != null:执行后续操作 return null; } }