热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringCloud(三)Zuul

Zuul有了eureka、feign和hystrix后,基本上就搭建了简易版的分布式项目,但仍存在一些问题,比如:1、如果我们的微服务中有很多个独立服务都要对外提供服务,那么我们要

Zuul

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

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

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

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


使用 Zuul 构建 API 网关



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


    org.springframework.cloud
    spring-cloud-starter-netflix-zuul


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client



  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();
}
}


原文链接:https://www.cnblogs.com/wzp123456/p/15732054.html



推荐阅读
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • Java EE 平台集成了多种服务、API 和协议,旨在支持基于 Web 的多层应用程序开发。本文将详细介绍 Java EE 中的 13 种关键技术规范,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 龙蜥社区开发者访谈:技术生涯的三次蜕变 | 第3期
    龙蜥社区的开发者们通过自己的实践和经验,推动着开源技术的发展。本期「龙蜥开发者说」聚焦于一位资深开发者的三次技术转型,分享他在龙蜥社区的成长故事。 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文记录了在Windows 8.1系统环境下,使用IIS 8.5和Visual Studio 2013部署Orchard 1.7.2过程中遇到的问题及解决方案,包括503服务不可用错误和web.config配置错误。 ... [详细]
  • 在尝试通过自定义端口部署Spring Cloud Eureka时遇到了连接失败的问题。本文详细描述了问题的现象,并提供了有效的解决方案,以帮助遇到类似情况的开发者。 ... [详细]
  • 本文介绍了如何利用Python中的Matplotlib库来绘制三维点云数据,并展示其外接的最大边界框。通过具体代码示例,帮助读者理解点云数据的可视化方法。 ... [详细]
  • 深入解析:存储技术的演变与发展
    本文探讨了从单机文件系统到分布式文件系统的存储技术发展过程,详细解释了各种存储模型及其特点。 ... [详细]
  • Redis:缓存与内存数据库详解
    本文介绍了数据库的基本分类,重点探讨了关系型与非关系型数据库的区别,并详细解析了Redis作为非关系型数据库的特点、工作模式、优点及持久化机制。 ... [详细]
  • 深入解析Dubbo:使用与源码分析
    本文详细介绍了Dubbo的使用方法和源码分析,涵盖其架构设计、核心特性和调用流程。 ... [详细]
  • 本文详细介绍了 Spark 中的弹性分布式数据集(RDD)及其常见的操作方法,包括 union、intersection、cartesian、subtract、join、cogroup 等转换操作,以及 count、collect、reduce、take、foreach、first、saveAsTextFile 等行动操作。 ... [详细]
author-avatar
柠檬泪滴味道186
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有