
Spring Cloud之路由网关Zuul
发布日期:2021-05-06 15:33:29
浏览次数:12
分类:技术文章
本文共 7229 字,大约阅读时间需要 24 分钟。
一:Zuul简单介绍
- 简介 这是Netflix构建微服务的另一个组件—>智能路由网关组件Zuul。它一般用于构建 边界服务(Edge Service),主要用于动态路由,过滤,监控,弹性伸缩和安全。
- Zuul的主要作用 ⑴Zuul,Ribbon以及Euraka相结合,可以实现智能路由和负载均衡的功能,Zuul能够 将请求流量按照某种策略分发到集群状态的多个服务实例。 ⑵网关将所有服务的API接口统一聚合,并且统一对外暴露。外界系统调用API接口 时,都是由路由对外暴露的API接口,外界系统不需要知道微服务系统中各个服务 相互调用的复杂性。微服务系统也保护了其内部微服务单元的API接口,防止其被 外界直接调用,导致服务的敏感信息对外暴露。 ⑶网关服务可以用来做用户身份认证和权限认证,防止非法请求操作API接口,对服 务器起到保护作用。 ⑷网关可以实现监控功能,实时日志输出,对请求进行记录。 ⑸网关可以用来实现流量监控,在高流量的情况下,对服务进行降级。 ⑹API接口从内部服务分离出来,方便做测试。
- Zuul的工作原理 Zuul是通过Servlet来实现的,Zuul通过自定义的ZuulServlet(类似于Spring MVC的 DispatchServlet)来对请求进行控制,ZuulServlet是Zuul的核心Servlet,它的作用是初始 化ZuulFilter,并且去编排这些ZuulFilter的执行顺序,这个类中存在一个service()方法,执 行了过滤器执行的逻辑。Zuul的核心是一系列的过滤器,可以在Http请求的发起和响应返 回期间执行一系列的过滤器。Zuul包含了以下4种过滤器: a:PRE过滤器—它是在请求路由到具体的服务之前执行的,这种类型的过滤器可以 做安全验证,例如身份验证,参数验证等。 b:ROUTING过滤器—它用于将请求路由到具体的微服务实例。在默认情况下,它 使用Http Client进行网络请求。 c:POST过滤器—它是在请求已经被路由到具体的微服务之后执行的。一般情况下 用作收集统计信息,指标,以及将响应传输到客户端。 d:EEOR过滤器—它是在其它过滤器发生错误时执行的。
- Zuul过滤器的关键特性 ⑴简介 Zuul采取了动态读取,编译和运行这些过滤器。过滤器之间不能直接相互通信, 而是通过RequestContext对象来共享数据,每个请求都会创建一个RequestContext 对象。 ⑵特性如下 a:Type(类型)—Zuul过滤器的类型,这个类型决定了过滤器在请求的哪个阶段 起作用,例如PRE,POST阶段等。 b:Execution Order(执行顺序)—这个参数规定了过滤器的执行顺序,order的值 越小,越先执行。 c:Criteria(标准)—表示Filter执行所需的条件 d:Action(行动)—表示如果符合执行条件,则执行Action(即逻辑代码)
- Zuul请求的生命周期 ⑴流程图如下
⑵流程图的逻辑如下 当一个客户端Request请求进入Zuul网关服务时,会先进入到PRE Filters过滤器,进行 一系列的验证,操作或者判断,当然我们也可以使用自定义放入过滤器。后面再交给过滤器 ROUTING Filters去进行请求的路由转发,将请求路由到具体的服务实例进行逻辑处理,最后 返回处理结果。当具体的服务处理完后,最后由POST Filters过滤器进行处理,这个会将结果 返回给客户端。当然PRE,ROUTING,POST这3个处理器处理请求的过程中一旦处理任何问题, 都会调用ERROR Filters进行处理,最后将问题返回到客户端。
二:案例实战
- 首先我们搭建Zuul服务
⑴创建启动类EurekaZuulClientApplication.java文件
⑵创建配置文件application.yml文件
由上面的配置我们能够知道程序名称为service-zuul 服务中心的注册地址为:http://peer1:8761/eureka/ 程序的端口为5000 并且我们这里配置了zuul.routs.eurekaClient.path为/eurekaClientApi/**, zuul.routs.eurekaClient.service-id为eureka-client,那么这两个配置表示 的就是将以/eurekaClientApi开头的Url路由到eureka-client服务。当然其中 zuul.routs.eurekaClient中的eurekaClient是自定义的。同理下面的两个服务 eureka-ribbon-client和eureka-feign-client也是一样。 ⑶在pom.xml文件中添加依赖
4.0.0 com.kgf chapter5-2 1.0-SNAPSHOT eureka-zuul-client eureka-zuul-client org.springframework.cloud spring-cloud-starter-netflix-zuul org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test - 测试效果 ⑴ 依次启动工程eureka-server,eureka-client(注意这里需要启动两个实例,端口分别为8762,8763),eureka-ribbon-client, eureka-feign-client和eureka-zuul-client ⑵ 效果
a:那么现在我们首先通过zuul服务直接访问eureka-client的接口 路径: 第一次:
第二次:
通过上面的效果我们是可以发现zuul默认和Ribbon结合实现了负载均衡的功能。 这说明zuul起到了路由的作用。 b:当然如果我们不需要Ribbon去做这个负载均衡,我们可以指定服务实例的Url,一旦指定 了url,这时候就不需要service-id了,如下:
效果如下,不管请求几次都是8762这个服务的实例了。
c:当然,如果我们既想要去指定Url,又想做负载均衡,那么我们就需要自己维护 负载均衡的服务注册列表。
再次看看效果: 第一次:
第二次:
三:我们在Zuul的配置上可以添加一个前缀
- 在application.yml配置文件中添加一个属性prefix即可
- 效果
四:在Zuul上配置熔断器
- 简介 在Zuul中实现熔断功能需要实现FallbackProvider的接口。实现该接口的两个方法, 一个是getRoute()方法,用于指定熔断功能应用于哪些路由的服务,另一个方法fallbackResponse() 为进入熔断功能时执行的逻辑。
- 创建接口FallbackProvider的实现类MyFallbackProvider.java
package com.kgf.eureka.zuul.hystrix;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;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;@Componentpublic class MyFallbackProvider implements FallbackProvider { @Override public String getRoute() { return "eureka-client";//实现对eureka-client服务的熔断 } @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { return new ClientHttpResponse() { @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream("Error,I am the fallback".getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } @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() { } }; }}
- 依次启动工程eureka-server,eureka-client(注意这里需要启动两个实例,端口分别为8762,8763),eureka-ribbon-client, eureka-feign-client和eureka-zuul-client
- 效果
访问eureka-client接口正常展示
下面我们将eureka-client关掉效果:
- 如果我们将getRoute()方法的返回改为”*”,那么将对所有的路由服务都加熔断功能
五:在Zuul中使用过滤器
- 简介 zuul不仅只是路由,并且还能过滤,做一些安全验证,实现过滤器很简单,只要继承ZuulFilter,并且实现 ZuulFilter中的抽象方法,包括filterType()和filterOrder(),以及IZuulFilter的shouldFilter()和Object run()的两个方法。
- 实例代码 ⑴创建自定义的过滤器MyFilter.java
package com.kgf.eureka.zuul.filter;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import org.apache.commons.lang.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import com.netflix.zuul.ZuulFilter;import com.netflix.zuul.context.RequestContext;import com.netflix.zuul.exception.ZuulException;/** * 自定义过滤器 * @author 86136 * */@Componentpublic class MyFilter extends ZuulFilter { private static Logger log = LoggerFactory.getLogger(MyFilter.class); /** * filterType:返回一个字符串代表过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型,具体如下: * 1:pre:路由之前 * 2:routing:路由之时 * 3:post: 路由之后 * 4:error:发送错误调用 */ @Override public String filterType() { return "pre";//这里必须小写 } /** * 这个方法表示该过滤器是否过滤逻辑,如果为true,则执行run方法,如果为false,则不执行run方法 */ @Override public boolean shouldFilter() { return true; } /** * 这个run方法中是主要写具体过滤的逻辑的。 * 这里我们测试的例子是判断用户是否在请求参数中传递了token这个参数, * 如果没有传递这个参数,那么请求就不会被传递到具体的服务实例,直接返回相应状态码401 */ @Override public Object run() throws ZuulException { //获取RequestContext对象,因为过滤器直接不能直接通信,必须通过RequestContext来共享数据 RequestContext context = RequestContext.getCurrentContext(); //获取HttpServletRequest对象 HttpServletRequest request = context.getRequest(); //获取我们的参数标识 String accessToken = request.getParameter("token"); if(StringUtils.isBlank(accessToken)) { log.warn("token is empty!"); //如果参数为空,那么我们设置网关返回直接不路由到具体服务 context.setSendZuulResponse(false); //返回状态码为401 context.setResponseStatusCode(401); try { //将错误信息返回到前台 context.getResponse().getWriter().write("token is empty!"); } catch (IOException e) { return null; } } log.info("ok"); return null; } /** * 过滤的顺序 ,值越小越先执行该过滤器 */ @Override public int filterOrder() { return 0; }}
⑵依次启动工程eureka-server,eureka-client(注意这里需要启动两个实例,端口分别为8762,8763),eureka-ribbon-client, eureka-feign-client和eureka-zuul-client服务 a:访问浏览器路径:b: 访问浏览器路径:
c:总结 我们定义的pre类型的过滤器在请求被zuul路由转发之前,会对请求进行安全校验。
发表评论
最新留言
表示我来过!
[***.240.166.169]2025年03月31日 19时46分33秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
2020建筑电工(建筑特殊工种)实操考试视频及建筑电工(建筑特殊工种)作业模拟考试
2019-03-03
2020N1叉车司机模拟考试题库及N1叉车司机复审模拟考试
2019-03-03
2020熔化焊接与热切割考试及熔化焊接与热切割考试题库
2019-03-03
2020年G3锅炉水处理报名考试及G3锅炉水处理考试申请表
2019-03-03
2020年制冷与空调设备运行操作答案解析及制冷与空调设备运行操作考试总结
2019-03-03
2020年保育员(初级)考试资料及保育员(初级)新版试题
2019-03-03
2020年茶艺师(高级)考试内容及茶艺师(高级)考试申请表
2019-03-03
2021年烟花爆竹经营单位安全管理人员考试及烟花爆竹经营单位安全管理人员考试试卷
2019-03-03
2021年过氧化工艺试题及答案及过氧化工艺考试平台
2019-03-03
2021年重氮化工艺考试题库及重氮化工艺考试报名
2019-03-03
2021年车工(高级)考试总结及车工(高级)试题及答案
2019-03-03
2021年压力焊证考试及压力焊实操考试视频
2019-03-03
2021年低压电工考试及低压电工考试申请表
2019-03-03
2021年低压电工考试及低压电工考试申请表
2019-03-03
2021年A特种设备相关管理(电梯)考试APP及A特种设备相关管理(电梯)复审考试
2019-03-03
2021年美容师(初级)考试报名及美容师(初级)新版试题
2019-03-03
2021年N1叉车司机考试题及N1叉车司机复审模拟考试
2019-03-03
2021年危险化学品经营单位主要负责人考试APP及危险化学品经营单位主要负责人多少钱
2019-03-03
2021年T电梯修理考试技巧及T电梯修理模拟考试软件
2019-03-03
2021年电工(初级)考试及电工(初级)报名考试
2019-03-03