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. C/C++ Qt TabWidget 实现多窗体创建

    在开发窗体应用时通常会伴随分页,ToolBar组件可以实现顶部工具栏菜单,每一个ToolBar组件关联到一个TabWidget组件的Tab标签内,这样我们就可以实现一个复杂的多窗体分页结构,此类结构也 ...

  2. python第三天 列表和元组

    枚举 for in enumerate 循环输出字符串的内容并且输出它的索引信息: #判断索引为5的字符串是不是"您" is in Python提供了⼤量的内置数据结构,包含了列表 ...

  3. Unity——Js和Unity互相调用

    Unity项目可以打包成WebGl,打包后的项目文件: Build中是打包后的Js代码: Index.html是web项目的入口,里面可以调整web的自适应,也可以拿去嵌套: TemplateData ...

  4. 巩固javawbe第二天

    巩固内容: <!DOCTYPE> 声明 <!DOCTYPE>声明有助于浏览器中正确显示网页. 网络上有很多不同的文件,如果能够正确声明HTML的版本,浏览器就能正确显示网页内容 ...

  5. acute

    In Euclidean geometry, an angle is the figure formed by two rays, called the sides of the angle, sha ...

  6. Hadoop【Hadoop-HA搭建(HDFS、YARN)】

    目录 0.HDFS-HA的工作机制 1. HDFS-HA集群配置 1.1 环境准备 1.2 规划集群 1.3 配置Zookeeper集群 2. 配置HDFS-HA集群 3. 启动HDFS-HA集群 4 ...

  7. 多人协作解决方案,git flow的使用

    简介 Gitflow工作流程围绕项目发布定义了严格的分支模型. 为不同的分支分配了非常明确的角色,并且定义了使用场景和用法.除了用于功能开发的分支,它还使用独立的分支进行发布前的准备.记录以及后期维护 ...

  8. Java事务与JTA

    一.什么是JAVA事务 通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令.更简答的说就是:要么 ...

  9. 转 Android Lifecycle、ViewModel和LiveData

    转自:https://www.jianshu.com/p/982545e01d0a 1.概述 在I / O '17的时候,其中一个重要的主题是Architecture Components.这是一个官 ...

  10. 【Linux】【Services】【Project】Haproxy Keepalived Postfix实现邮件网关Cluster

    1. 简介: 1.1. 背景:公司使用exchange服务器作为邮件服务器,但是使用Postfix作为邮件网关实现病毒检测,内容过滤,反垃圾邮件等功能.原来的架构非常简单,只有两台机器,一个负责进公司 ...