前言:前面说过,由于微服务过多,可能某一个小业务就需要调各种微服务的接口,不可避免的就会需要负载均衡和反向代理了,以确保ui不直接与所有的微服务接口接触,所以我们需要使用一个组件来做分发,跨域等各种请求。
ZUUL是Netflix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用,它主要用作反向代理、Filter扩展、动态加载、动态路由、压力测试、弹性扩展、审查监控、安全检查等。
1、创建一个Maven工程,gateway-zuul,添加依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 添加spring-boot的maven插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2、在启动类上添加注解@EnableZuulProxy,声明ZUUL代理,通过观察Zuul的类库发现,zuul的依赖库中除了有它本身的核心包外还有actuator、hystrix的整合包,默认实现了监控和熔断机制,所有经过zuul的请求都会在hystrix命令中执行:
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
3、编写配置文件application.properties:
server.port=8000
spring.application.name=zuul-8000
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
#由于zuul中的actuator默认的安全权限为ture,需改为false,若不修改则会导致无法访问路由管理(localhost:8000/routes)
management.security.enabled=false
(注:下面的测试,是基于之前做的几个关于Ribbon、Hystrix的demo来做的,若感兴趣可以看一下我之前的文章:SpringCloud-客户端的负载均衡Ribbon(三)、SpringCloud-容错处理Hystrix熔断器(五))
4、测试路由网关是否启动:
分别启动 eureka-ribbon-server、 eureka-ribbon-client、 eureka-ribbon-client2 和 gateway-zuul,打开服务配置中心,并访问http://localhost:8000/client-8762/getUser:
通过网关访问成功!
5、测试负载均衡是否可用:
分别启动 eureka-ribbon-server、eureka-feign-hystrix-client、修改 eureka-ribbon-client2 端口为8763、修改 eureka-ribbon-client2 端口为8764 和 gateway-zuul,打开服务配置中心,并多次访问http://localhost:8000/client-8762/loadInstance,观察返回结果:
根据观察结果知,通过网关实现负载均衡!
6、测试熔断与路由端点是否可用:
熔断:
分别启动 eureka-ribbon-server、 eureka-feign-hystrix-client、 eureka-ribbon-client2 和 gateway-zuul,打开服务配置中心,并多次访问http://localhost:8000/client-8762/loadInstance,观察返回结果:
将CLIENT-87实例关闭,再次调用:
注:由于client-87的实例关闭后要等eureka将实例移除后,然后eureka通知zuul,zuul再将client-87从网关列表中移除,最后访问,才可以看到熔断,走回调函数了!
启动项目与上面 测试5相同,注意网关中的application.properties一定要将安全权限打开或者以其他方式,才可访问localhost:8000/routes/
#由于zuul中的actuator默认的安全权限为ture,需改为false,若不修改则会导致无法访问路由管理(localhost:8000/routes)
management.security.enabled=false
Zuul提供一个框架,可以对Groovy写的过滤器进行动态的加载、编译、运行。过滤器之间没有直接的相互通信,通过一个RequestContext的静态类中ThreadLocal变量来进行数据传递,过滤器类型:
PRE:这种过滤器在请求到达Origin Server之前调用。比如身份验证,在集群中选择请求的Origin Server,记log等;
ROUTING:在这种过滤器中把用户请求发送给Origin Server。发送给Origin Server的用户请求在这类过滤器中build。并使用Apache HttpClient或者NetfilxRibbon发送给Origin Server;
POST:这种过滤器在用户请求从Origin Server返回以后执行。比如在返回的response上面加response header,做各种统计等。并在该过滤器中把response返回给客户;
ERROR:在其他阶段发生错误时执行该过滤器;
客户定制:比如我们可以定制一种STATIC类型的过滤器,用来模拟生成返回给客户的response;
1、创建过滤器类,继承ZuulFilter抽象类,实现该方法:
/**
* @program: springcloud-example
* @description:
* @author:
* @create: 2018-06-20 16:53
**/
public class RequestLogFilter extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(RequestLogFilter.class);
/**
* @Description: 返回过滤器类型,就是上面介绍的那几种类型
* @Param:
* @return:
* @Author:
* @Date: 2018/6/20
*/
@Override
public String filterType() {
return "pre";
}
/**
* @Description:指定过滤器执行的顺序
* @Param:
* @return:
* @Author:
* @Date: 2018/6/20
*/
@Override
public int filterOrder() {
return 1;
}
/**
* @Description:指定该过滤器是否执行
* @Param:
* @return:
* @Author:
* @Date: 2018/6/20
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* @Description: 过滤器的具体方法逻辑
* @Param:
* @return:
* @Author:
* @Date: 2018/6/20
*/
@Override
public Object run() {
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String url = request.getRequestURL().toString();
logger.info("请求URL:"+url);
return null;
}
}
2、在启动类,将该过滤器注入到Spring容器中:
@Bean
public RequestLogFilter getRequestLogFilter() {
return new RequestLogFilter();
}
3、分别启动 eureka-ribbon-server、 eureka-ribbon-client、 eureka-ribbon-client2、 gateway-zuul测试:
参考书籍:《SpringCloud与Docker微服务架构实战》周力著
代码示例:https://gitee.com/lfalex/springcloud-example( eureka-feign-hystrix-client、 eureka-hystrix-client、 eureka-ribbon-client、 eureka-ribbon-client2、 eureka-ribbon-server、 gateway-zuul)