热门标签 | 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



推荐阅读
  • Spring Cloud因其强大的功能和灵活性,被誉为开发分布式系统的‘一站式’解决方案。它不仅简化了分布式系统中的常见模式实现,还被广泛应用于企业级生产环境中。本书内容详实,覆盖了从微服务基础到Spring Cloud的高级应用,适合各层次的开发者。 ... [详细]
  • 本文探讨了如何在日常工作中通过优化效率和深入研究核心技术,将技术和知识转化为实际收益。文章结合个人经验,分享了提高工作效率、掌握高价值技能以及选择合适工作环境的方法,帮助读者更好地实现技术变现。 ... [详细]
  • 深入解析Spring Cloud微服务架构与分布式系统实战
    本文详细介绍了Spring Cloud在微服务架构和分布式系统中的应用,结合实际案例和最新技术,帮助读者全面掌握微服务的实现与优化。 ... [详细]
  • 前言无论是对于刚入行工作还是已经工作几年的java开发者来说,面试求职始终是你需要直面的一件事情。首先梳理自己的知识体系,针对性准备,会有事半功倍的效果。我们往往会把重点放在技术上 ... [详细]
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • 深入解析:阿里实战 SpringCloud 微服务架构与应用
    本文将详细介绍 SpringCloud 在微服务架构中的应用,涵盖入门、实战和案例分析。通过丰富的代码示例和实际项目经验,帮助读者全面掌握 SpringCloud 的核心技术和最佳实践。 ... [详细]
  • 最近团队在部署DLP,作为一个技术人员对于黑盒看不到的地方还是充满了好奇心。多次咨询乙方人员DLP的算法原理是什么,他们都以商业秘密为由避而不谈,不得已只能自己查资料学习,于是有了下面的浅见。身为甲方,虽然不需要开发DLP产品,但是也有必要弄明白DLP基本的原理。俗话说工欲善其事必先利其器,只有在懂这个工具的原理之后才能更加灵活地使用这个工具,即使出现意外情况也能快速排错,越接近底层,越接近真相。根据DLP的实际用途,本文将DLP检测分为2部分,泄露关键字检测和近似重复文档检测。 ... [详细]
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • 本文详细介绍了Java的安装、配置、运行流程以及有效的学习方法,旨在帮助初学者快速上手Java编程。 ... [详细]
  • Spring Cloud学习指南:深入理解微服务架构
    本文介绍了微服务架构的基本概念及其在Spring Cloud中的实现。讨论了微服务架构的主要优势,如简化开发和维护、快速启动、灵活的技术栈选择以及按需扩展的能力。同时,也探讨了微服务架构面临的挑战,包括较高的运维要求、分布式系统的复杂性、接口调整的成本等问题。最后,文章提出了实施微服务时应遵循的设计原则。 ... [详细]
  • 本文作为SpringCloud Alibaba系列教程的第一部分,主要介绍如何搭建SpringCloud Alibaba的开发环境,帮助初学者快速入门。SpringCloud Alibaba是由阿里巴巴团队开源的一套微服务工具集,旨在简化分布式系统的构建过程。 ... [详细]
  • SpringCloud电商平台开发指南:实战案例解析
    本文详细介绍了基于SpringCloud构建的电商平台项目,涵盖了从技术选型到项目部署的全流程,旨在帮助开发者快速掌握电商平台的开发技巧。 ... [详细]
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社区 版权所有