Zuul

有了eureka 、 feign 和 hystrix 后,基本上就搭建了简易版的分布式项目,但仍存在一些问题,比如:

1、如果我们的微服务中有很多个独立服务都要对外提供服务,那么我们要如何去管理这些接口?特别是当项目非常庞大的情况下要如何管理?

2、在微服务中,一个独立的系统被拆分成了很多个独立的服务,为了确保安全,权限管理也是一个不可回避的问题,如果在每一个服务上都添加上相同的权限验证代码来确保系统不被非法访问,那么工作量也就太大了,而且维护也非常不方便。

所以出现了网关,它就像一个安检站一样,所有外部的请求都需要经过它的调度与过滤,然后 API 网关来实现请求路由、负载均衡、权限验证等功能。

使用 Zuul 构建 API 网关

  1. 创建spring boot工程并添加依赖:

    <!--添加 spring cloud 的 zuul 的起步依赖--> <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    <!--添加 spring cloud 的 eureka 的客户端依赖--> <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
  2. 在入口类上添加@EnableZuulProxy 注解,开启 Zuul 的 API 网关服务功能:

    @SpringBootApplication
    @EnableEurekaClient
    @EnableZuulProxy
    public class SpringcloudZuulApplication { public static void main(String[] args) {
    SpringApplication.run(SpringcloudZuulApplication.class, args);
    } }
  3. 在application.yml中添加路由规则

    # 配置路由规则
    zuul:
    routes:
    hello:
    path: /api-zuul/**
    serviceId: springcloud-consumer

    说明:以上配置的路由规则就是匹配所有符合/api-zuul/**的请求,只要路径中带有/api-zuul/都将被转发到 springcloud-consumer 服务上。比如:localhost:8766/api-zuul/web/hello转发到 http://localhost:8764/web/hello

  4. 构建成功

使用 Zuul 进行请求过滤

  1. 定义一个过滤器类并继承自 ZuulFilter,并将该 Filter 作为一个 Bean:

    @Component
    public class AuthFilter extends ZuulFilter {
    @Override
    public String filterType() {
    return "pre";
    } @Override
    public int filterOrder() {
    return 0;
    } @Override
    public boolean shouldFilter() {
    return true;
    } @Override
    public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    String token = request.getParameter("token");
    if (token == null) {
    ctx.setSendZuulResponse(false);
    ctx.setResponseStatusCode(401); ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
    ctx.setResponseBody("非法访问");
    }
    return null;
    }
    }
    • filterType 方法的返回值为过滤器的类型,决定了过滤器在哪个生命周期执行,pre 表示在路由之前执行过滤器,其他值还有 post、error、route 和 static,当然也可以自定义。
    • filterOrder 方法表示过滤器的执行顺序,当过滤器很多时,我们可以通过该方法的返回值来指定过滤器的执行顺序。
    • shouldFilter 方法用来判断过滤器是否执行,true 表示执行,false 表示不执行。
    • run 方法则表示过滤的具体逻辑,如果请求地址中携带了 token 参数的话,则认为是合法请求,否则为非法请求,如果是非法请求的话,首先设置ctx.setSendZuulResponse(false),表示不对该请求进行路由,然后设置响应码和响应值。这个 run 方法的返回值目前暂时没有任何意义,可以返回任意值。
  2. 不携带token,localhost:8766/api-zuul/web/hello

  3. 携带token,localhost:8766/api-zuul/web/hello?token=213

Zuul 的路由规则

  1. 在前面的例子中,

    zuul:
    routes:
    hello:
    path: /api-zuul/**
    serviceId: springcloud-consumer

    当访问地址符合 /api-zuul/ 规则的时候,会被自动定位到springcloud-consumer 服务上,有点麻烦,还可以简化为:

    zuul:
    routes:
    springcloud-consumer: /api-zuul/**

    zuul.routes 后面跟着的是服务名,服务名后面跟着的是路径规则,这种配置方式更简单。

  2. 默认情况下,Eureka 上所有注册的服务都会被 Zuul 创建映射关系来进行路由。

    #默认的规则
    zuul.routes.springcloud-consumer.path=/springcloud-consumer/**
    zuul.routes.springcloud-consumer.serviceId=springcloud-consumer

    但如果希望 springcloud-service-provider 作为服务提供者只对服务消费者提供服务,不对外提供服务:

    zuul.ignored-services=springcloud-service-provider

    还可以进一步细化,比如不想给/hello 接口路由:

    zuul.ignored-patterns=/**/hello/**

    也可以统一的为路由规则增加前缀:

    zuul.prefix=/myapi

    路由规则通配符:

  3. 一般情况下 API 网关只是作为各个微服务的统一入口,但是有时候我们可能也需要在 API 网关服务上做一些特殊的业务逻辑处理,那么我们可以让请求到达 API 网关后,再转发给自己本身,由 API 网关自己来处理,那么我们可以进行如下的操作:

@RestController
public class GateWayController {
@RequestMapping("/api/local")
public String hello() {
return "exec the api gateway.";
}
}

在 application.yml 中:

zuul:
routes:
gateway:
path: /gateway/**
url: forward:/api/local

Zuul 的异常处理

首先看一下Zuul 请求的生命周期:

  • 正常情况下所有的请求都是按照 pre、route、post 的顺序来执行,然后由 post 返回 response
  • 在 pre 阶段,如果有自定义的过滤器则执行自定义的过滤器
  • pre、routing、post 的任意一个阶段如果抛异常了,则执行 error 过滤器

    有两种方式统一处理异常:
  1. 禁用 zuul 默认的异常处理 SendErrorFilter 过滤器,然后自定义我们自己的 Errorfilter 过滤器

    zuul:
    routes:
    springcloud-consumer: /api-zuul/**
    SendErrorFilter:
    error:
    disable: true
    @Component
    public class ErrorFilter extends ZuulFilter {
    private static final Logger logger =
    LoggerFactory.getLogger(ErrorFilter.class);
    @Override
    public String filterType() {
    return "error";
    }
    @Override
    public int filterOrder() {
    return 1;
    }
    @Override
    public boolean shouldFilter() {
    return true;
    }
    @Override
    public Object run() throws ZuulException {
    try {
    RequestContext context = RequestContext.getCurrentContext();
    ZuulException exception = (ZuulException)context.getThrowable();
    logger.error("进入系统异常拦截", exception);
    HttpServletResponse response = context.getResponse();
    response.setContentType("application/json; charset=utf8");
    response.setStatus(exception.nStatusCode);
    PrintWriter writer = null;
    try {
    writer = response.getWriter();
    writer.print("{code:"+ exception.nStatusCode +",message:\""+
    exception.getMessage() +"\"}");
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    if(writer!=null){
    writer.close();
    }
    }
    } catch (Exception e) {
    ReflectionUtils.rethrowRuntimeException(e);
    }
    return null;
    }
    }

    在 AuthFiler 里的run()方法添加异常 int i = 10 / 0

  2. 自定义全局 error 错误页面

    开启 zuul 默认的异常处理 SendErrorFilter 过滤器,并注释掉 ErrorFilter 类

@RestController
public class ErrorHandlerController implements ErrorController {
/**
* 出异常后进入该方法,交由下面的方法处理
*/
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public Object error(){
RequestContext ctx = RequestContext.getCurrentContext();
ZuulException exception = (ZuulException)ctx.getThrowable();
return exception.nStatusCode + "--" + exception.getMessage();
}
}

SpringCloud(三) Zuul的更多相关文章

  1. springcloud学习之路: (三) springcloud集成Zuul网关

    网关就是做一下过滤或拦截操作 让我们的服务更加安全 用户访问我们服务的时候就要先通过网关 然后再由网关转发到我们的微服务 1. 新建一个网关服务Module 2. 依然选择springboot工程 3 ...

  2. Oauth2.0 整合springCloud的Zuul 解决关键BUG 报错信息:Principal must not be null

    不清楚Oauth2.0 的 可以查看我前几篇博文 2018.4.8 补充 我出现这个原因:是我在资源服务器使用了 如下图所示 Principal Oauth2.0 提供的获取用户信息的方法 使其找到相 ...

  3. SpringCloud之Zuul:服务网关

    Zuul在Web项目中的使用见上文<SpringBoot中使用Zuul>,下面例子为Zuul在Spring Cloud的使用. 开发工具:IntelliJ IDEA 2019.2.3 一. ...

  4. Spring-Cloud之Zuul路由网关-6

    一.为什么需要Zuul? Zuul 作为微服务系统的网关组件,用于构建边界服务( Edge Service ),致力于动态路由.过滤.监控.弹性伸缩和安全.Zuul 作为路由网关组件,在微服务架构中有 ...

  5. SpringCloud之Zuul网关原理及其配置

    Zuul是spring cloud中的微服务网关.网关: 是一个网络整体系统中的前置门户入口.请求首先通过网关,进行路径的路由,定位到具体的服务节点上. Zuul是一个微服务网关,首先是一个微服务.也 ...

  6. 非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了!

    Zuul是spring cloud中的微服务网关.网关:是一个网络整体系统中的前置门户入口.请求首先通过网关,进行路径的路由,定位到具体的服务节点上. Zuul是一个微服务网关,首先是一个微服务.也是 ...

  7. SpringCloud网关ZUUL集成consul

    最近一直在搞基于springcloud的微服务开发,为了不限定微服务开发语言,服务发现决定采用consul不多说上代码 pom文件 <project xmlns="http://mav ...

  8. SpringCloud系列——Zuul 动态路由

    前言 Zuul 是在Spring Cloud Netflix平台上提供动态路由,监控,弹性,安全等边缘服务的框架,是Netflix基于jvm的路由器和服务器端负载均衡器,相当于是设备和 Netflix ...

  9. springcloud的Zuul配置重试和fallback

    可以参考如下blog: SpringCloud学习03之api服务网关zuul反向代理及重试配置 springCloud学习04之api服务网关zuul回退fallback 注意:重试的开启需要处理幂 ...

随机推荐

  1. Codeforces 643F - Bears and Juice(思维题)

    Codeforces 题目传送门 & 洛谷题目传送门 首先直接暴力枚举显然是不现实的,我们不妨换个角度来处理这个问题,考虑这 \(R_i\) 个瓶子中每一瓶被哪些熊在哪一天喝过. 我们考虑对这 ...

  2. Codeforces 306D - Polygon(随机化+乱搞)

    Codeforces 题目传送门 & 洛谷题目传送门 中考终于结束了--简单写道题恢复下状态罢. 首先这一类题目肯定没法用一般的方法解决,因此考虑用一些奇淫的乱搞做法解决这道题,不难发现,如果 ...

  3. [linux] 大批量删除任务

    一不小心投了巨多任务,或者投递的资源不合理时,想批量杀掉这些任务. kill的方法就不说了,我这里用qdel的方法. 用了这么一条命令: qstat |sed '1,2d' |awk -F' ' '{ ...

  4. xshell的快捷复制粘贴设置

    今天试着用xshell连接Linux,运行一些命令的时候想快点复制粘贴实现效率,却发现还要右键选择复制,再右键选择粘贴,很是麻烦. 看了一下xshell的设置,其实可以自己设置成快捷方式 以xshel ...

  5. Linux非root安装Python3以及解决SSL问题

    说明 接上一篇. [Linux]非root安装Python3及其包管理 上一篇虽然成功安装了Python3及一些常用的模块,但因为一直装不上SSL模块,导致一些包无法安装,尝试了不少方法都失败了(网上 ...

  6. mongoDB整个文件夹拷贝备份还原的坑

    现网有一个mongoDB数据库需要搬迁到新服务器,开发那边的要求是先搬迁现在的数据库过去,然后剩下的以后他们用程序同步. 数据库大楷20G左右,现网是主备仲裁的,停掉备点,拷贝了全部文件. 新服务器也 ...

  7. 云原生时代的 APM

    作者 | 刘浩杨 来源|尔达 Erda 公众号 ​APM 的全称是 Application Performance Management(应用性能管理),早在 90 年代中期就有厂商提出性能管理的概念 ...

  8. 安全相关,xss

    XSS XSS,即 Cross Site Script,中译是跨站脚本攻击:其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS. ...

  9. Linux磁盘分区(三)之查看磁盘分区常用命令

    Linux磁盘分区(三)之查看磁盘分区常用命令转自https://blog.csdn.net/x356982611/article/details/77893264 1.df     df -T 总的 ...

  10. 查看linux系统CPU和内存命令

    cat /proc/cpuinfo查看linux系统的CPU型号.类型以及大小,如下图所示.   通过greap命令根据Physical Processor ID筛选出多核CPU的信息.   cat ...