一、定义
Zuul包含了请求的路由和过滤的2个主要的功能:
其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求处理过程进行干预,是实现请求校验,服务聚合等功能的基础.
Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得
注意:Zuul服务最终还是会注册进Eureka
提供=代理+路由+过滤三大功能
功能:路由和过滤
官网资料:https://github.com/Netflix/zuul
二、路由的基本配置
1、Model模块microservicecloud-zuul-gateway-9527
pom文件
<dependencies>
<!--网关依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!-- 将微服务provider侧注册进eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- actuator监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
yml文件
server:
port: 9527
spring:
application:
name: microservicecloud-zuul-gateway
eureka:
client:
service-url:
defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/,http://localhost:7001/eureka/
instance:
instance-id: gateway-9527.com
prefer-ip-address: true
info:
app.name: atguigu-microcloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$
host修改
127.0.0.1 myzuul.com
主启动类
新增注解@EnableZuulProxy
@SpringBootApplication
@EnableZuulProxy
public class Zuul_9527_StartSpringCloudApp {
public static void main(String[] args) {
SpringApplication.run(Zuul_9527_StartSpringCloudApp.class);
}
}
启动服务
三个eureka集群
一个服务提供类microservicecloud-provider-dept-8001
一个路由
启动成功之后,在注册中心看是否注册上去没有
测试
不用路由 http://localhost:8001/dept/findById/1
使用路由 http://myzuule.com:9527/microservicecloud-dept/dept/findById/1
2、路由访问规则
yml文件
server:
port: 9527
spring:
application:
name: microservicecloud-zuul-gateway
eureka:
client:
service-url:
defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/,http://localhost:7001/eureka/
instance:
instance-id: gateway-9527.com
prefer-ip-address: true
info:
app.name: atguigu-microcloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$
#路由访问规则
zuul:
routes:
mydept: #这个名称随便定义
serviceId: microservicecloud-dept #路由到那个服务
path: /mydept/** #映射地址
访问路径: http://myzuule.com:9527/mydept/dept/findById/1
相关参数:
参数:
zuul:
#ignored-services: microservicecloud-dept 忽略一个
ignored-services: "*" #忽略所有的
prefix: /atguigu #统一访问前缀
routes:
mydept.serviceId: microservicecloud-dept 这个转发到那个服务去
mydept.path: /mydept/** #映射
也可以这样写
routes:
mydept://一种规则 自定义
serviceId: microservicecloud-dept 这个转发到那个服务去
path: /mydept/** #映射
#简洁写法:
microservicecloud-dept: /mydept/**
3、自定义过滤器
-
Filter 的生命周期
Filter 的生命周期有 4 个,分别是 “PRE”、“ROUTING”、“POST” 和“ERROR”,整个生命周期可以用下图来表示
案例代码:
/**
* 自定义过滤zuul器
*/
@Component
public class TokenFilter extends ZuulFilter {
/**
* PRE: 该类型的filters在Request routing到源web-service之前执行。用来实现Authentication、选择源服务地址等
* ROUTING:该类型的filters用于把Request routing到源web-service,源web-service是实现业务逻辑的服务。这里使用HttpClient请求web-service。
* POST:该类型的filters在ROUTING返回Response后执行。用来实现对Response结果进行修改,收集统计数据以及把Response传输会客户端。
* ERROR:上面三个过程中任何一个出现错误都交由ERROR类型的filters进行处理。
* 主要关注 pre、post和error。分别代表前置过滤,后置过滤和异常过滤。
* 如果你的filter是pre的,像上一篇那种,就是指请求先进入pre的filter类,你可以进行一些权限认证,日志记录,或者额外给Request增加一些属性供后续的filter使用。pre会优先按照order从小到大执行,然后再去执行请求转发到业务服务。
* 再说post,如果type为post,那么就会执行完被路由的业务服务后,再进入post的filter,在post的filter里,一般做一些日志记录,或者额外增加response属性什么的。
* 最后error,如果在上面的任何一个地方出现了异常,就会进入到type为error的filter中
* @return
*/
// 过滤器类型 pre 表示在 请求之前进行拦截
@Override
public String filterType() {
return "pre";
}
// 过滤器的执行顺序。当请求在一个阶段的时候存在多个多个过滤器时,需要根据该方法的返回值依次执行
//filter执行顺序,通过数字指定。数字越大,优先级越低。
@Override
public int filterOrder() {
return 0;
}
//判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有请求都会生效。
// 实际运用中我们可以利用该函数来指定过滤器的有效范围。
@Override
public boolean shouldFilter() {
return true;
}
//执行业务逻辑
@Override
public Object run() throws ZuulException {
//获取上下文
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
//可以从url参数获取,也可以从请求头里面获取 cookie里面获取
String token = request.getParameter("token");
if(StringUtils.isBlank(token)){
//false 不会继续往下执行 不会调用服务接口了 网关直接响应给客户了
currentContext.setSendZuulResponse(false);
currentContext.setResponseStatusCode(404);
currentContext.setResponseBody("tonken不能为空");
return null;
}
//否则执行业务代码
return 0;
}
}