SpringCloud(Greenwich版)Zuul实现微服务网关
推荐以下稳定版本号:
Spring Boot: 2.1.9.RELEASE
一、Zuul简介
Zuul 是 Netflix 开源的微服务网关组件,Zuul 其实相当于是设备(手机APP)和应用的 Web 网站后端所有请求的前门。它可以和 Eureka、Ribbon、Hystrix 等组件配合使用,支持动态路由与过滤功能。
Zuul 使用了各种不同类型的过滤器,这些过滤器帮助我们执行以下功能:
-
身份验证与安全性:识别每个资源的身份验证要求,并拒绝那些与要求不符合的请求。
-
洞察和监控:在边缘跟踪有意义的数据和统计信息,以便为我们提供准确的生产视图。
-
压力测试:逐渐增加到群集的流量以评估性能。
-
动态路由:根据需要将请求动态路由到不同的后端群集。
-
负载分配:为每种类型的请求分配容量,并丢弃超出限制的请求。
-
静态响应处理:直接在边缘构建一些响应,而不是将其转发到内部集群。
-
多区域弹性:跨域AWS Region进行请求路由,以便扩大我们的ELB(Elastic Load Balancing)使用范围。
二、路由(Router)
1)build.gradle项目依赖
dependencies {
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client'
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-zuul'
}
2)application.yaml配置文件
server:
port: 8080
spring:
application:
name: zuul-service
zuul:
routes:
provider:
path: /provider-service/**
url: http://localhost:8081/
serviceId: PROVIDER-SERVICE
zuul.routes下的属性:
-
id:
-
path:动态路由映射路径规则
-
url:映射路径对应的实际微服务地址
-
serviceId:映射到此路由的服务ID
3)启动类ZuulServiceApplication.java
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注解作为一个服务实例注册到服务治理体系中去。所以,启动类不需要再添加这两个注解了。
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 服务上了:
以下是几种标准的过滤器类型,它们对应于一个请求的典型生命周期:
-
PRE:转发到微服务之前执行的过滤器。
-
ROUTING:在路由请求时执行的过滤器。
-
POST:在执行微服务获取返回值之后执行的过滤器。
-
ERROR:
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 {
/**
*功能描述:定义过滤器的类型
* pre
* routing
* post
* 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;
}
}