SpringCloud学习之Zuul路由转发、拦截和熔断处理(七)
Spring Cloud Zuul
服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中,除了具备服务路由、均衡负载功能之外,它还具备了权限控制等功能。
Spring Cloud Netflix中的Zuul就担任了这样的一个角色,为微服务架构提供了前门保护的作用,同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面,使得服务集群主体能够具备更高的可复用性和可测试性。
在Spring Cloud体系中, Spring Cloud Zuul 封装了Zuul组件,作为一个API网关,负责提供负载均衡、反向代理和权限认证。
Zuul工作机制
过滤器机制
Zuul的核心是一系列的filters, 其作用类似Servlet框架的Filter,Zuul把客户端请求路由到业务处理逻辑的过程中,这些filter在路由的特定时期参与了一些过滤处理,比如实现鉴权、流量转发、请求统计等功能。Zuul的整个运行机制,可以用下图来描述。
过滤器的生命周期
Filter的生命周期有4个,分别是“PRE”、“ROUTING”、“POST”、“ERROR”,整个生命周期可以用下图来表示。
基于Zuul的这些过滤器,可以实现各种丰富的功能,而这些过滤器类型则对应于请求的典型生命周期。
PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器。
除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
Zuul中默认实现的Filter
Zuul默认实现了很多Filter,这些Filter如下面表格所示。
类型 | 顺序 | 过滤器 | 功能 |
---|---|---|---|
pre | -3 | ServletDetectionFilter | 标记处理Servlet的类型 |
pre | -2 | Servlet30WrapperFilter | 包装HttpServletRequest请求 |
pre | -1 | FormBodyWrapperFilter | 包装请求体 |
route | 1 | DebugFilter | 标记调试标志 |
route | 5 | PreDecorationFilter | 处理请求上下文供后续使用 |
route | 10 | RibbonRoutingFilter | serviceId请求转发 |
route | 100 | SimpleHostRoutingFilter | url请求转发 |
route | 500 | SendForwardFilter | forward请求转发 |
post | 0 | SendErrorFilter | 处理有错误的请求响应 |
post | 1000 | SendResponseFilter | 处理正常的请求响应 |
我们先看看Zuul的工作原理,Zuul是主要起路由转发和路由拦截作用的,这里直接说Zuul和Feign集成的工作流程如下:
新建一个Consumer服务消费模块,他的pom.xml添加如下依赖:
看看他的主程序:
再看看application.yml里的配置文件:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
server:
port: 8768
spring:
application:
name: service-ribbon
zuul:
routes:
#标识你服务的名字,这里可以自己定义,一般方便和规范来讲还是跟自己服务的名字一样
service-feign:
#服务映射的路径,通过这路径就可以从外部访问你的服务了,目的是为了不爆露你机器的IP,面向服务的路由了,给你选一个可用的出来,
path: /service-feign/**
serviceId: service-feign
启动我们的注册中心服务、至少一个服务提供者、启动Feign服务消费者、启动我们的Zuul服务消费者,启动正常:
打开浏览器器,输入http://localhost:8768/service-feign/hello?name=111这是我们基于Feign的请求转发
打开浏览器器,输入http://localhost:8768/service-feign/hi?name=111这是我们基于RestTemplate的请求转发
可以看到,我们成功将我们的路由请求转发到Feign服务消费者模块上了,接下来我们要实现以下Zuul对请求的拦截和熔断处理,
拦截就是在转发之前或者之后当请求到达Feign之前做拦截处理,这个是很重要的功能,熔断是当我们路由转发请求的服务不可用该怎么处理响应呢?
一、路由请求拦截
package com.xu.serviceconsumer.component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class MyTokenFilter extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(MyTokenFilter.class);
//四种类型:pre,routing,error,post
//pre:主要用在路由映射的阶段是寻找路由映射表的
//routing:具体的路由转发过滤器是在routing路由器,具体的请求转发的时候会调用
//error:一旦前面的过滤器出错了,会调用error过滤器。
//post:当routing,error运行完后才会调用该过滤器,是在最后阶段的
@Override
public String filterType() {
return "pre";
}
//自定义过滤器执行的顺序,数值越大越靠后执行,越小就越先执行
@Override
public int filterOrder() {
return 1;
}
//控制过滤器生效不生效,可以在里面写一串逻辑来控制
@Override
public boolean shouldFilter() {
return true;
}
//执行过滤逻辑
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String url = request.getRequestURL().toString();
logger.info("请求URL:"+url);
String token = request.getParameter("name");
if (token == null){
context.setSendZuulResponse(false);
context.setResponseStatusCode(401);
context.setResponseBody("there is no request parameter name");
return null;
}
return null;
}
}
简单看一下代码知道这个过滤器继承了ZuulFilter,在run()方法里日志输出了请求的URL路径和对参数是否有name做了简单的拦截过滤,请求http://localhost:8768/service-feign/hello?
可以看到这个Zuul的路由过滤器成功的对这个请求拦截过滤了,最后看一下控制台信息也可以看到成功输出打印了请求的URL
二、路由熔断
package com.xu.serviceconsumer.component;
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 MyFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
return "service-feign";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
System.out.println("route:"+route);
System.out.println("exception:"+cause.getMessage());
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(("Sorry, the service "+getRoute()+" is unavailable now.").getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
注意这里的一段代码
我们的熔断路由器配置的是service-feign(就是我们zuul请求路由的这个这个服务),我们关闭这个服务,保留其他之前开启的服务,请求http://localhost:8768/service-feign/hi?name=111
自此,我们可以
自此,说明我们自定义的熔断器已经起作用了,这课的内容到此为止,下回再见!
===============================================================================
如果您觉得此文有帮助,可以打赏点钱给我支付宝或扫描二维码
SpringCloud学习之Zuul路由转发、拦截和熔断处理(七)的更多相关文章
- SpringCloud学习系列之六 ----- 路由网关Zuul基础使用教程
前言 在上篇中介绍了SpringCloud Config的完美使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由网关 ...
- SpringCloud学习之zuul
一.为什么要有网关 我们先看一个图,如果按照consumer and server(最初的调用方式),如下所示 这样我们要面临如下问题: 1. 用户面临着一对N的问题既用户必须知道每个服务.随着服务的 ...
- SpringCloud 进阶之Zuul(路由网关)
1. Zuul(路由网关) Zuul 包含了对请求的路由和过滤两个最主要的功能; 路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础; 过滤功能:负责对请求的处理过程进行干 ...
- SpringCloud学习笔记-zuul网关
公司目前使用的是dubbo方式实现微服务,想试水改造接口层服务为Spring Cloud, 以下是网络拓补图. 第一层负载均衡可以用nginx或者zuul(即有2层zuul), 本图画的是nginx. ...
- Zuul路由转发规则
定制的路由规则的主要功能: 1.路由表中包含源路径,微服务名称,目标路径 2.Endpoint粒度配置支持 3.路由支持1对1精确路由 4.源路径可以前缀/**格式来模糊路由 5.目标路径可以使用前缀 ...
- SpringCloud 学习(5) --- Zuul(一)基本概念、配置
[TOC] Spring Cloud eureka:注册中心 服务端:提供注册 客户端:进行注册 ribbon:负载均衡(集群) Hystrix:熔断器,执行备选方案 Feign:远程调用 Zuul: ...
- SpringCloud学习之Zuul统一异常处理及回退
一.Filter中统一异常处理 其实在SpringCloud的Edgware SR2版本中对于ZuulFilter中的错误有统一的处理,但是在实际开发当中对于错误的响应方式,我想每个团队都有自己的处理 ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- spring cloud 2.x版本 Zuul路由网关教程
前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...
随机推荐
- Spring Boot 2.x 入门前的准备-安装 Java JDK
本章节介绍在以 window7.window10 为代表的 window 和 mac book 下安装 Java 编译和开发环境JDK 1.8,在 window 上安装 Java JDK 的步骤,本章 ...
- node.js+mysql环境搭建
https://www.jianshu.com/p/9b338095cbe8 node.js+mysql环境搭建 0x01 前言 随着html web技术的发展,和全栈式开发的需求,对于前端人员来讲, ...
- 后端——框架——持久层框架——Mybatis——《Mybatis从入门到精通》读书笔记——初篇
1.Mybatis知识点 框架的知识点大致可以分为三个部分 基础: 介绍编写增,删,改,查: 动态标签: config配置文件 Mapper配置文件 插件:常见的插件有三个 pageHelper:分页 ...
- Update(Stage4):spark_rdd算子:第1节 RDD_定义_转换算子:深入RDD
一. 二.案例:详见代码.针对案例提出的6个问题: 假设要针对整个网站的历史数据进行处理, 量有 1T, 如何处理? 放在集群中, 利用集群多台计算机来并行处理 如何放在集群中运行? 简单来讲, 并行 ...
- python学习 —— post请求方法的应用
声明:本篇仅基于兴趣以及技术研究而对B站曾经发生过的抢楼事件背后相关技术原理进行研究而写.请不要将其作为私利而对B站以及B站用户体验造成影响!谢谢合作!若本文对B站及其用户带来困扰,请联系本人删除本文 ...
- leetCode练题——9. Palindrome Number
1.题目 9. Palindrome Number Determine whether an integer is a palindrome. An integer is a palindrome ...
- php 高级 多台web服务器共享session的方法
解决多台web服务器共享session的问题,至少有以下三种方法: 一.将本该保存在web服务器磁盘上的session数据保存到cookie中 即用cookie会话机制替代session会话机制, ...
- django 模版标签笔记
一.模板变量笔记:1.在模版中使用变量,需要将变量放到‘{{}}’中.'{{ 变量 }}'2.如果想访问对象的属性,可以通过'对象.属性名'的方式访问3.如果想要访问一个字典的key对应的value, ...
- python中的 dir()内置函数的作用以及使用方法
dir() 内置函数的作用 python 内置方法有很多,无论是初学者还是精通python 的程序员都不能全部即住所有的方法,这时候 dir() 方法就非常有用了,使用 dir()函数可以查看对象内的 ...
- elk安装2.0版本,自己总结,比较细致 es单机的安装
用root用户会报错,版本6之前还是可以用root用户启动的,针对es的保护,数据的一些问题,6之后就不允许了. 启动成功 下面验证一下 可以直接用浏览器访问,接受http访问 配置,因为没有暴露端 ...