一、Zuul介绍
- Zuul是netflix开源的一个APIGateway服务器,本质上是一个Web Servlet应用
- Zuul在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul相当于是设备和Netflix网站后端所有请求的前门。
- Zuul的例子可以参考Netflix在Github上的Simple Webapp,可以按照Netflix在GitHub wiki上文档说明来进行使用。
二、Zuul解决了什么问题?
三、案例
1.创建项目
2.添加相关的依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR11</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--表示这是一个SpringCloud Eureka的Client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.配置文件
在属性文件中我们同样的需要添加Eureka的相关信息
spring.application.name=Zuul-getway
server.port=9020
# 设置服务注册中心的地址
eureka.client.service-url.defaultZone=http://bb:1234@192.168.134.129:8761/eureka/,http://bb:1234@192.168.134.131:8761/eureka/
4.启动类
我们需要在启动类中添加Zuul的注解
@EnableZuulProxy
@SpringBootApplication
public class SpringcloudZuulGetwayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringcloudZuulGetwayApplication.class, args);
}
}
5.测试
5.1 直接访问
5.2 通过Zuul网关访问
**访问地址:**http://网关地址:网关端号/要访问的服务的名称/要访问的服务中心的接口地址
四、路由规则
1.指定路由
根据客户端提交的请求地址直接路由到服务地址
spring.application.name=Zuul-getway
server.port=9020
# 设置服务注册中心的地址
eureka.client.service-url.defaultZone=http://bb:1234@192.168.134.129:8761/eureka/,http://bb:1234@192.168.134.131:8761/eureka/
zuul.routes.shop-product-provider.path=/biao/**
zuul.routes.shop-product-provider.url=http://127.0.0.1:9099/
说明:
zuul.routes. :固定的
shop-product-provider :自定义的
path :固定的
/biao/ ** : 表示请求的URL地址
zuul.routes.shop-product-provider.url=http://127.0.0.1:9099/ :表示当用户的请求是 http://xxx/biao/** 时则路由到 http://127.0.0.1:9081/ 服务处理
2.指定服务路由名称
上面的指定路由是根据服务端提交的请求地址路由到具体的服务中心,这种方式其实是不太灵活的,我们可以路由到Eureka中注的服务名称
2.1 第一种方式
# 服务名称 路由
zuul.routes.shop-product-provider.path=/biao/**
zuul.routes.shop-product-provider.service-id=shop-product-provider
2.2 第二种方式
# 服务名称 路由 第二种方式:shop-product-provider必须是我们要请求的服务的名称
zuul.routes.shop-product-provider.path=/biao/**
3.路由的排除方式
排除路由,也就是该路由会忽略掉某几个服务,即使客户端发送了请求也访问不了
zuul.ignored-services=eureka-provider
如果有多个服务要排除。这时可以通过“,”连接的方式来排除多个服务
zuul.ignored-services=eureka-provider1,eureka-provider2
如果有很多歌要排除的服务,一个个来写太麻烦了,这时我们可以先排除所有的服务,然后再添加我们要开放的服务即可。
# 先排除所有的服务
zuul.ignored-services=*
# 然后再放开特定的服务
zuul.routes.shop-product-provider.path=/biao/**
如果我们要针对某个服务中特殊接口来处理,我们也可以通过关键字处理
# 先排除所有的服务包含 findAll关键字的请求
zuul.ignored-services=/**/findAll/**
# 然后再放开特定的服务 同时也会排除findAll服务
zuul.routes.shop-product-provider.path=/biao/**
4.指定路由前缀
# http://127.0.0.1:9080/biao/abc/product/findAll zuul.prefix=/biao
zuul.routes.shop-product-provider.path=/abc/**
五、自定义网关管理器
Zuul的核心是一系列的Filters,其作用可以类比Servlet框架的Filter。我们实际开发中会有很多的需求涉及到自定义的过滤器。
1.创建自定义过滤器
package com.biao.zuul;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 自定义的网关过滤器
*/
@Component
public class LoggerFilter extends ZuulFilter {
/**
* 指定过滤器的类型
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤器的执行顺序
* 数值越小,优先级越高
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否开启过滤器 默认值 false
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤器要执行的逻辑代码
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
//获取Request上下文环境
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
System.out.println("----自定义过滤器执行了------>" + request.getRequestURL().toString());
return null;
}
}
2.演示效果
启动一个provider,启动网关服务,然后查询访问,再查看控制台输出
3.相关方法介绍
自定义过滤器中的相关方法介绍
3.1 filterType
过滤器的类型,它用字符串来表示;在Zuul中默认定义了四种不同生命周期的过滤器类型,具体如下:
- pre:可以在请求被路由之前调用。一般用于身份权限验证、记录调用日志等等。
- routing:在路由执行之后被调用。
- post:在routing和error过滤器之后被调用。可用于信息收集、统计信息例如性能指标,对response的结构做些特殊处理。
3.2 filterOrder
用int值来定义过滤器的执行顺序,数值越小优先级越高
3.3 shouldFilter
返回一个boolean类型来判断过滤器是否要执行
3.4 run
逻辑处理。一般2个用途
- 请求前拦截,对请求进行验证判断,如果请求无效就直接断路;如果有效可再加工处理
- 请求结果后处理,即对结果做一些加工处理
4.请求生命周期
5.案例分析
模拟一个身份认证的过滤器
/**
* 过滤器要执行的逻辑代码
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
//获取Request上下文环境
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
System.out.println("----自定义过滤器执行了------>" + request.getRequestURL().toString());
//做一个身份认证
String token = request.getParameter("token");
if (token == null){
//没有传递身份认证信息 拦截请求
// 表示 请求结束 不再继续向下请求
currentContext.setSendZuulResponse(false);
// 添加一个响应码
currentContext.setResponseStatusCode(401);
// 响应类型
currentContext.setResponseBody(" {\"result\":\"token is null \"}");
// 响应类型
currentContext.getResponse().setContentType("text/json;charset=utf-8");
}
return null;
}