热门标签 | 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实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • MACElasticsearch安装步骤及验证方法
    本文介绍了MACElasticsearch的安装步骤,包括下载ZIP文件、解压到安装目录、启动服务,并提供了验证启动是否成功的方法。同时,还介绍了安装elasticsearch-head插件的方法,以便于进行查询操作。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Spring学习(4):Spring管理对象之间的关联关系
    本文是关于Spring学习的第四篇文章,讲述了Spring框架中管理对象之间的关联关系。文章介绍了MessageService类和MessagePrinter类的实现,并解释了它们之间的关联关系。通过学习本文,读者可以了解Spring框架中对象之间的关联关系的概念和实现方式。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
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社区 版权所有