Spring-Cloud之Zuul路由网关-6
一、为什么需要Zuul?
Zuul 作为微服务系统的网关组件,用于构建边界服务( Edge Service ),致力于动态路由、过滤、监控、弹性伸缩和安全。Zuul 作为路由网关组件,在微服务架构中有着非常重要的作用,主要体现在以下6个方面。
1)Zuul Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能, Zuul 能够将请求流量按某种策略分发到集群状态的多个服务实例。
2)网关将所有服务的 API 接口统一聚合,并统一对外暴露。外界系统调用 API 接口时,都是由网关对外暴露的 API 接口,外界系统不需要知道微服务系统中各服务相互调用的复杂性。微服务系统 保护了其内部微服务单元的 API 接口 防止其被外界直接调用,导致服务的敏感信息对外暴露。
3)网关服务可以做用户身份认证和权限认证,防止非法请求操作 API 接口,对服务器起到保护作用。
4)网关可以实现监控功能,实时日志输出,对请求进行记录。
5)网关可以用来实现流量监控。在高流量的情况下,对服务进行降级。
6)API 接口从内部服务分离出来 方便做测试。
二、Zuul的工作原理
Zuul 是通过 Servlet 来实现的, Zuul 通过自定义的 Zuul Servlet (类似于 Spring MVC的DispatcServlet 〕来对请求进行控制。 Zuul 的核心是一系列过滤器,可以在 Http 请求的发起和响应返回期间执行一系列的过滤器。 Zuul 包括以下4种过滤器。
1)PRE 过滤器:它是在请求路由到具体的服务之前执行的,这种类型的过滤器可以做安全验证,例如身份验证、 参数验证等。
2)ROUTING 过滤器:它用于将请求路由到具体的微服务 。在默认情况下,它使用Http Client 进行网络请求。
3)POST 过滤器:它是在请求已被路由到微服务后执行的一般情况下,用作收集统计信息、指标,以及将响应传输到客户端。
4)ERROR 过滤器:它是在其他过滤器发生错误时执行的。
1)Type (类型):Zuul 过滤器的类型,这个类型决定了过滤器在请求的哪个阶段起作用,例如 Pre Post 阶段等。
2)Execution Order (执行顺序) :规定了过滤器的执行顺序, Order 的值越小,越先执行
3)Criteria (标准):Filter 行所需的条件。
4)Action (行动):如果符合执行条件,则执行 Action (即逻辑代码)。

当一个客户端 Request 请求进入 Zuul网关服务时,网关先进入“pre filter ,进行一系列的验证、操作或者判断。然后交给“routing filter ”进行路由转发,转发到具体的服务实例进行逻辑处理、返回数据。当具体的服务处理完后,最后由“post filter进行处理,该类型的处理器处理完之后,将 Response 信息返回给客户端。
ZuulServlet是Zuul的核心Servlet,ZuulServlet的作用是初始化ZuulFilter。并编排这些顺序,具体的逻辑在service()方法中
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
try {
... try {
this.preRoute();
} catch (ZuulException var12) {
this.error(var12);
this.postRoute();
return;
} try {
this.route();
} catch (ZuulException var13) {
this.error(var13);
this.postRoute();
return;
} try {
this.postRoute();
} catch (ZuulException var11) {
this.error(var11);
}
} catch (Throwable var14) {
this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName()));
} finally {
RequestContext.getCurrentContext().unset();
}
}
三、搭建具体的Zuul应用服务。
1)加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2)编写启动程序加上@EnableZuulProxy注解。
package com.cetc; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
3)加入配置(服务端口为8682):
server:
port: 8682
spring:
application:
name: zuul
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8670/eureka/ # 实际开发中建议使用域名的方式
zuul:
routes:
test:
path: /test/**
url: http://127.0.0.1:8673/
ribbon:
path: /ribbon/**
serviceId: rest
feign:
path: /feign/**
serviceId: feign
说明:上面的为基本配置:
zuul.routes.test/ribbon/feign:中的test/ribbon/feign为自定义配置。
path:为Zuul中代理的路径。
serviceId:为服务的名称。
url:为具体的地址,不存在负载均衡的问题。(主要用于外部服务加入)
4)测试:启动项目包含Eureka-Server, 2个Eureka-Client,Ribbon中的Rest,Feign和Zuul。端口分别为:8670、8673/8674、8675、8676、8682。
效果如下:
测试接口为:
http://127.0.0.1:8682/test/api/test/getPort
http://127.0.0.1:8682/ribbon/api/ribbon/getPort
http://127.0.0.1:8682/feign/api/feign/getPort
可见这里的访问:使用url的方式默认没有负载均衡的,所以不建议使用,使用ribbon和feign两种方式都是可以进行负载均衡的。
5)如果想使用url的方式来做负载均衡那么就要自己维护访问列表。配置如下:
zuul:
routes:
test-r:
path: /test-r/**
serviceId: test-r
test-r:
ribbon:
listOfServers: http://127.0.0.1:8673/, http://127.0.0.1:8674/
ribbon:
eureka:
enabled: false
说明:这里禁用ribbon不影响前面配置好的服务。但是会影响Zuul调用ribbon的rest或者feign服务,如果这两个服务存在负载均衡,那么调用的时候就存在负载均衡问题。所以一般建议不要这样使用。
测试:
6)如果想加入具体的版本号,可以加入如下配置:
zuul:
prefix: /v1
访问方式为:http://127.0.0.1:8682/v1/test/api/test/getPort。在链接中加入版本号。
四、Zuul加入熔断器:
默认实现FallbackProvider接口,加入容器即可
package org.springframework.cloud.netflix.zuul.filters.route; import org.springframework.http.client.ClientHttpResponse; public interface FallbackProvider {
String getRoute(); ClientHttpResponse fallbackResponse(String var1, Throwable var2);
}
实现为:
package com.cetc.config; import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream; @Component
public class ZuulFallbackProvider implements FallbackProvider { @Override
public String getRoute() {
return "*";
} @Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
} @Override
public int getRawStatusCode() throws IOException {
return 200;
} @Override
public String getStatusText() throws IOException {
return "OK";
} @Override
public void close() { } @Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("error".getBytes());
} @Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
return httpHeaders;
}
};
}
}
测试:关闭feign测试接口为:
五、在Zuul中自定义filter:
package com.cetc.filter; import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; @Component
public class CustomZuulFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
} @Override
public int filterOrder() {
return 0;
} @Override
public boolean shouldFilter() {
//是否开启过滤逻辑,开启后运行run()方法
return true;
} @Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest();
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
HttpServletResponse response = requestContext.getResponse();
requestContext.setSendZuulResponse(false);
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
try {
response.getWriter().write("token is empty");
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
测试:
是不是感觉这类有点验证的味道了。通过自定义的过滤就能达到请求过滤的目的。实现过程如下:
六、Zuul的常见使用方式。
Zuul 是采用了类似于 Spring MVC DispatchServlet 来实现的,采用的是异步阻塞模型,所以性能比 Ngnix 差。由于 Zuul和其他 Netflix 组件可以相互配合、无缝集成 Zuul 很容易就能实现负载均衡、智能路由和熔断器等功能。在大多数情况下 Zuul 都是以集群的形式在的。由于Zuul的横向扩展能力非常好,所以当负载过高时,可以通过添加实例来解决性能瓶颈。
1)一种常见的使用方式是对不同的渠道使用不同的 Zuul 来进行路由,例如移动端共用Zuul一个网关实例。Web 端用另一个Zuul 网关实例,其他的客户端用另外一个Zuul 实例进行路由。
2)另外一种常见的集群是通过 Ngnix和Zuul 相互结合来做负载均衡。暴露在最外面的是Ngnix 主从双热备进行 Keepalive, Ngnix 经过某种路由策略,将请求路由转发到 Zuul 集群上,Zuul 最终将请求分发到具体的服务上。
七、源码地址:https://github.com/lilin409546297/spring-cloud/tree/master/zuul
Spring-Cloud之Zuul路由网关-6的更多相关文章
- spring cloud 学习之路由网关(zuul)
学习自方志朋的博客 http://blog.csdn.net/forezp/article/details/69939114 在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费. ...
- zuul路由网关集成ssl,实现http到https的转变
1 前言 最近几天刚开始接触微信小程序的开发,才接触到了https的概念(微信小程序中的请求必须为https请求,不然请求无法成功).https算是对http的安全封装,在http的基础上加了ssl证 ...
- spring cloud 2.x版本 Zuul路由网关教程
前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...
- Spring Cloud Alibaba | Nacos动态网关路由
Spring Cloud Alibaba | Gateway基于Nacos动态网关路由 本篇实战所使用Spring有关版本: SpringBoot:2.1.7.RELEASE Spring Cloud ...
- spring cloud 通过zuul网关去请求的时候报404的几个原因。
spring cloud 中 zuul 网关的那些坑: 1.检查你的服务是否正常启动. 2.检查你的服务是否正常注册到注册中心. 3.zuul网关的路由规则是会把你注册在注册中心的serviceId ...
- 【七】zuul路由网关
一.zuul是什么?zuul 包含以下两个最主要的功能:1.路由功能: 负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础.2.过滤器功能: 则负责对请求的处理过程进行干预,是实现请 ...
- SpringCloud 进阶之Zuul(路由网关)
1. Zuul(路由网关) Zuul 包含了对请求的路由和过滤两个最主要的功能; 路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础; 过滤功能:负责对请求的处理过程进行干 ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- SpringCloud的入门学习之概念理解、Zuul路由网关
1.Zuul路由网关是什么? 答:Zuul包含了对请求的路由和过滤两个最主要的功能,其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进 ...
- SpringCloud学习笔记(八):Zuul路由网关
概述 是什么? Zuul包含了对请求的路由和过滤两个最主要的功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请 ...
随机推荐
- vlc for mac设置中文的方法
VLC for mac是一款mac系统下的多媒体播放器,支持播放MPEG-1.MPEG-2.MPEG-4.DivX.MP3和OGG,以及DVD.VCD.等各种流媒体协议在内的多种协议格式,并且能够对电 ...
- 欧拉法求解常微分方程(c++)
#include<iostream> #include<iomanip> using namespace std; int main() { double x, y, h; ...
- jvm (一)jvm结构 & 类加载 & 双亲委托模型
参考文档: jvm内幕-java虚拟机详解:http://www.importnew.com/17770.html 常量池:https://www.jianshu.com/p/c7f47de2ee80 ...
- APISIX系列 | 使用 docker-apisix 安装APISIX服务
官方仓库:https://github.com/iresty/docker-apisix 官方仓库 拉取 git clone git@github.com:iresty/docker-apisix.g ...
- kotlin基础 条件控制 when
When 表达式 when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件. when 既可以被当做表达式使用也可以被当做语句使用.如果它被当做表达式,符合条件的分支的值就是整个表达式的值, ...
- springmvc@RequestMapping-params参数规则
springmvc@RequestMapping-params参数规则 https://blog.csdn.net/qq_33439525/article/details/78193190 版权声明: ...
- android mk 预编译库
LOCAL_PATH := $(call my-dir) #include $(CLEAR_VARS) # OpenCV #OPENCV_CAMERA_MODULES:=on #OPENCV_INST ...
- java多线程(一)创建线程的四种方式
1. 什么是并发与并行 要想学习多线程,必须先理解什么是并发与并行 并行:指两个或多个事件在同一时刻发生(同时发生). 并发:指两个或多个事件在同一个时间段内发生. 2. 什么是进程.线程 进 ...
- OpenShift 3.11离线环境的jenkins演示
离线安装完成后,一般情况下只装了个基础环境,catalog镜像没有导入,本文主要侧重在jenkins的一些环境设置和演示. 1.导入镜像 首先follow下面链接下载镜像 https://docs.o ...
- ubuntu 16 typora 安装 ,14系统的不管用。。
# sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE linuxidc@linuxidc:~ ...