Zuul是什么?
Zuul是Netflix开源的微服务网关,可以和Eureka、Ribbon、Hystrix等组件配合使用,而Spring Cloud对Zuul进行了整合和增强,Zuul默认使用的HTTP客户端是Apache HTTPClient,Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,Zuul默认和Ribbon结合实现了负载均衡的功能。
Zuul使用很多不同类型的过滤器,那么这些过滤器的功能有哪些呢?
-
身份验证和安全性:确定每个资源的身份验证要求并拒绝不满足这些要求的请求
-
洞察和监控:跟踪有意义的数据和统计数据,以便我们提供准确的生产视图
-
动态路由:根据需要动态的将请求路由到不同的后端集群
-
压力测试:逐渐增加集群的流量以衡量性能
-
Load Shedding:为每种类型的请求分配容量并删除超过限制的请求
-
静态响应处理:直接在边缘构建一些响应,而不是将它们转发到内部集群
以上是官方的,开源的jar实际上并没有这么多功能,可能他们内部用的有这些功能
Zuul的组件
- zuul-core-zuul核心库:包含编译和执行过滤器的核心功能。
- zuul-simple-webapp-zuul Web应用程序实例:展示了如何使用zuuk-core构建应用程序。
- zuul-netflix-lib包:将其他NetflixOSS组件添加到Zuul中,例如使用功能区进去路由请求处理。
- zuul-netflix-webapp-webapp:它将zuul-core和zuul-netflix封装成一个简易的webapp工程包。
搭建Zuul服务
单独创建一个新的服务,server-zuul
配置server-zuul的pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
在启动类加入@EnableZuulProxy,开启zuul
/**
* zuul路由网关服务
*
* @author: Aaron
* @date: 2020/1/15 09:51
* @param:
* @description:
* @return:
*/
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
在application.yml配置服务的基本信息和路由规则
#配置端口
server:
port: 8085
#配置服务名称
spring:
application:
name: server-zuul
eureka:
client:
service-url:
#配置注册中心地址
defaultZone: http://peer1:8081/eureka
#配置路由规则
zuul:
#写法1:自定义服务路径
routes:
server-user: /test1/**
server-org: /test2/**
#忽略指定服务,多个服务用逗号隔开,ps:若想忽略所有服务,改成【'*'】即可
# ignored-services: server-user,server-org
依次启动注册中心、user服务、org服务、zuul服务
访问地址:http://localhost:8085/test2/org/test?name=Aaron 、http:localhost:8085/test1/user/self?name=Aaron
如果能够正常显示 my name is Aaron,说明zuul起到了路由的作用。
服务过滤
zuul除了路由,过滤也是一个很重要的功能,它可以帮助我们在进入服务之前或者之后做一个自定义校验,配置自己的过滤规则
创建AccessTokenFliter.java类,配置token的校验规则
package com.yun.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* AccessToken验证
*
* @author Aaron
* @date 2020/1/16 10:18
*/
@Component
@Log4j2
public class AccessTokenFilter extends ZuulFilter {
/**
* 过滤的类型
* 1、pre:路由之前
* 2、routing:路由之时
* 3、post:路由之后
* 4、error:发送错误调用
*
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 过滤的顺序,默认就好
*
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 是否过滤
*
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
//获取请求地址中的token参数,参数的位置可以根据需求来
Object accessToken = request.getParameter("token");
if (accessToken == null) {
log.warn("token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(502);
try {
ctx.getResponse().getWriter().write("token is empty");
} catch (Exception e) {
log.error(e);
}
return null;
}
//
// 校验token的有效性,这里就不写了,根据自己的校验规则写
//
log.info("ok");
return null;
}
}
重启服务之后再次调用http://localhost:8085/test1/user/self?name=Aaron,返回结果如下图,token is empty 说明我们的拦截起到了作用
现在我们再加上token参数试一下,http://localhost:8085/test1/user/self?name=Aaron&token=1111,就可以正常返回了