Springcloud 微服务实战笔记 Zuul

优点

  1. 解决路由规则与服务实例维护问题。
  2. 对于类似签名校验、登录校验在微服务架构中的冗余问题。

入门使用

构建网关

  1. pom.xml引入 spring-cloud-starter-netflix-zuul

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>
    
  2. 应用主类增加@EnableZuulProxy注解

  3. 增加配置信息,主要是路由规则信息

    由于zuul已实现与eureka无缝整合,配置路由规则时候无需配置具体的URL,而是映射到具体的服务即可。比如: /api1/** 对应的就是请求SPRING-CLOUD-STUDY-DEMO服务

    通过指定Eureka Server服务注册中心的位置,除了将自己注册成服务之外,还可以让Zuul能够获取微服务实力清单,以实现path映射服务,再从服务中挑选实例来进行请求转发的完整路由机制。

    server:
      port: 7777
      
    spring:
      application:
        name: spring-cloud-study-zuul
    
    zuul:
    #需要忽略的头部信息,不在传播到其他服务
        sensitive-headers: Access-Control-Allow-Origin
        ignored-headers: Access-Control-Allow-Origin,H-APP-Id,Token,APPToken
        routes:
         apis1:
          path: /api1/**
          #serviceId: spring-cloud-study-demo
          serviceId: SPRING-CLOUD-STUDY-DEMO
         apis2:
          path: /api2/**
          url: http://127.0.0.1:9999/
         apis3:
          path: /api23/**
          url: https://www.baidu.com/
    

请求过滤

Zuul允许开发者在API网关上通过自定义过滤器来实现对请求的拦截与过滤,实现的方式很简单,只需要继承ZuulFilter抽象类并实现抽象方法即可。比如:

@Component
public class WebSocketFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return "pre";
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String upgradeHeader = request.getHeader("Upgrade");
        if (null == upgradeHeader) {
            upgradeHeader = request.getHeader("upgrade");
        }
        if (null != upgradeHeader && "websocket".equalsIgnoreCase(upgradeHeader)) {
            context.addZuulRequestHeader("connection", "Upgrade");
        }
        return null;
    }
}
package com.didispace.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;

/**
 * 校验请求中是否包含accessToken参数,如果没有包含则返回401
 */
public class AccessFilter extends ZuulFilter  {

    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();

        log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());

        Object accessToken = request.getParameter("accessToken");
        if(accessToken == null) {
            log.warn("access token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            return null;
        }
        log.info("access token ok");
        return null;
    }

}

●filterType:过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。这里定义为pre,代表会在请求被路由之前执行。 ●filterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。 ●shouldFilter:判断该过滤器是否需要被执行。这里我们直接返回了 true,因此该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的有效范围。 ● run : 过 滤 器 的 具 体 逻 辑 。 这 里 我 们 通 过ctx.setSendZuulResponse(false)令 zuul 过滤该请求,不对其进行路由,然后通过 ctx.setResponseStatusCode(401)设置了其返回的错误码 , 当 然 也 可 以 进 一 步优 化 我 们 的 返 回 , 比 如 , 通 过ctx.setResponseBody(body)对返回的body内容进行编辑等。

总结

●它作为系统的统一入口,屏蔽了系统内部各个微服务的细节。 ●它可以与服务治理框架结合,实现自动化的服务实例维护以及负载均衡的路由转发。 ●它可以实现接口权限校验与微服务业务逻辑的解耦。 ●通过服务网关中的过滤器,在各生命周期中去校验请求的内容,将原本在对外服务层做的校验前移,保证了微服务的无状态性,同时降低了微服务的测试难度,让服务本身更集中关注业务逻辑的处理。

进阶使用

路由详解

  1. 传统路由配置:直接path对应到具体的地址,多个地址则使用逗号分隔开
  2. 服务路由配置:path对应服务名即可,由于zuul整合了eureka,zuul可获取服务实例的地址清单,然后通过负载均衡策略,可在清单中选择一个具体的实例进行转发就能完成路由工作。
  3. 服务路由默认规则:zuul已经自动实现了zuul.routes.=/serviceId/** 路由规则配置,当然由于某些服务可能需要禁止可使用zuul.ignored-services=来排除服务

自定义路由映射规则

实现很简单,只需要在API网关工程中,增加Bean,比如:

@Bean
public PatternServiceRouteMapper serviceRouteMapper(){
  return new PatternServiceRouteMapper(
  "(? <name>^.+)-(? <version>v.+$)",
  "${version}/${name}");
}

通过上述代码就实现将userservice-v1和userservice-v2路径,修改为/v1/userservice/ 和 /v2/userservice/ 这样带有版本号前缀的路径。

忽略表达式

比如,以快速入门中的示例为基础,如果不希望/hello 接口被路由,那么我们可以这样设置:

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

路由前缀

为了方便全局地为路由规则增加前缀信息,Zuul提供了zuul.prefix 参数来进行设置,比如,希望为网关上的路由规则都增加/api前缀,那么我们可以在配置文件中增加配置:

zuul.prefix=/api

Cookie与头信息

默认情况下,Spring Cloud Zuul在请求路由时,会过滤掉HTTP请求头信息中的一些敏感信息,防止它们被传递到下游的外部服务器。默认的敏感头信息通过zuul.sensitiveHeaders参数定义,包括Cookie、SetCookie、Authorization三个属性。所以,我们在开发Web项目时常用的Cookie在Spring Cloud Zuul网关中默认是不会传递的,这就会引发一个常见的问题:如果我们要将使用了 Spring Security、Shiro等安全框架构建的Web应用通过Spring Cloud Zuul构建的网关来进行路由时,由于Cookie信息无法传递,我们的Web应用将无法实现登录和鉴权。怎么解决?

  1. 方式一:对指定路由开启自定义敏感头
    zuul.routes.<router>.customSensitiveHeaders=true
    
  2. 方式二:将指定路由的敏感头设置为空
    zuul.routes.<router>.sensitiveHeaders=
    

比较推荐使用这两种方法,仅对指定的Web应用开启对敏感信息的传递,影响范围小,不至于引起其他服务的信息泄露问题。

过滤器详解

过滤器

功能:请求的路由和过滤

路由:将外部请求转发到具体的微服务实例上,实现外部访问统一入口的基础。

过滤:负责对请求的处理过程进行干预,实现请求校验、服务聚合等功能的基础。

过滤器必须包含4个基本特征:过滤类型、执行顺序、执行条件、具体操作。对应4个抽象方法:

String filterType(); // 过滤器的类型
int filterOrder(); // 过滤器的执行顺序
boolean shouldFilter(); // 判断该过滤器是否要执行
Object run(); // 过滤器的具体逻辑

过滤器类型:

■pre:可以在请求被路由之前调用。 ■routing:在路由请求时被调用。 ■post:在routing和error过滤器之后被调用。 ■error:处理请求时发生错误时被调用。

请求生命周期

主要过程:

  1. pre,主要进行请求路由之前做一些前置加工,比如请求的校验等。
  2. routing,路由请求转发阶段,将外部请求转发到具体服务实例上去的过程。
  3. post,此时可以获取到请求信息,也可以获取到实例返回信息,在此阶段可进行一些加工或者转换等操作。
  4. error,此阶段只有在上述阶段中发生异常时候才会触发,最终流向哈市post,将最终结果返回给客户端。

核心过滤器

Spring cloud zuul默认实现了一批核心过滤器,主要如下图:

过滤器执行过程

com.netflix.zuul.http.ZuulServlet 实现如下:

@Override
    public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
        try {
            init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);

            // Marks this request as having passed through the "Zuul engine", as opposed to servlets
            // explicitly bound in web.xml, for which requests will not have the same data attached
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();

            try {
                preRoute();
            } catch (ZuulException e) {
                error(e);
                postRoute();
                return;
            }
            try {
                route();
            } catch (ZuulException e) {
                error(e);
                postRoute();
                return;
            }
            try {
                postRoute();
            } catch (ZuulException e) {
                error(e);
                return;
            }

        } catch (Throwable e) {
            error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
        } finally {
            RequestContext.getCurrentContext().unset();
        }
    }

通过配置禁用过滤器

zuul.<SimpleClassName>.<filterType>.disable=true

代表过滤器的类名 比如:ErrorFilter

代表过滤器类型,比如:error。

参考资料:

《Spring Cloud微服务实战》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/293056.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

苹果Vision Pro将于1月27日上市!

在无数期待中&#xff0c;苹果全新产品Vision Pro头显终于定下上市日期。 彭博社记者马克古曼&#xff08;Mark Gurman&#xff09;于近日在X&#xff08;前推特&#xff09;平台爆料了这一信息&#xff0c;预计苹果Vision Pro头显将于2024年1月27日率先在美国上市。 在过去看…

LeetCode 641. 设计循环双端队列

难度&#xff1a;Medium 641. 设计循环双端队列 设计实现双端队列。 实现 MyCircularDeque 类: MyCircularDeque(int k) &#xff1a;构造函数,双端队列最大为 k 。boolean insertFront()&#xff1a;将一个元素添加到双端队列头部。 如果操作成功返回 true &#xff0c;否…

Java CPU或内存使用率过高问题定位教程

简介 Spring cloud微服务广泛应用后&#xff0c;服务的监控和运维压力也与日俱增&#xff0c;经常有服务出现CPU或者内存使用率过高的告警&#xff0c;那么遇到这样的问题我们该如何排查呢&#xff1f;我们可以借助哪些工具来定位问题呢&#xff1f;本文将介绍一下遇到此类问题…

案例精选|淄博绿能燃气工程有限公司日志审计系统建设方案

淄博绿能燃气工程有限公司&#xff0c;成立于1994年&#xff0c;前身为淄博市煤气公司管道液化气分公司。公司业务主要涉及天然气、液化气等市政工程施工及城镇燃气供应等领域&#xff0c;具有市政公用工程施工总承包二级资质&#xff0c;《压力管道安装许可证》压力管道安装GB…

亚信安慧AntDB数据库:数字化时代的数据库创新引领者

AntDB数据库以其卓越的创新能力&#xff0c;集中体现在融合统一与实时处理两大关键领域。作为一款服务全国超过10亿用户的分布式数据库&#xff0c;其独特之处在于长期积累的经验、多样性的支持能力、快速响应的数据处理速度以及卓越的系统稳定性。AntDB不仅仅是一个数据库系统…

Node.js+Express+Mysql实现分页查询

接收请求代码 router.get(/api/user/page, async (req, res) > {let pageNo req.query.pageNo;let pageSize req.query.pageSize;const startIndex (pageNo - 1) * pageSize;const queryString SELECT * FROM sys_user LIMIT ${startIndex}, ${pageSize};data await …

【React系列】父子组件通信—props属性传值

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. 认识组件的嵌套 组件之间存在嵌套关系&#xff1a; 在之前的案例中&#xff0c;我们只是创建了一个组件App&…

Netty实战(待完善)

Netty组件 1. Bootstrap, ServerBootstrap Netty 中 Bootstrap 类是客户端程序的启动引导类&#xff0c;ServerBootstrap 是服务端启动引导类。 2. NioEventLoop, NioEventLoopGroup NioEventLoop 中维护了一个线程和任务队列&#xff0c;支持异步提交执行任务&#xff0c;…

小梅哥Xilinx FPGA学习笔记20——无源蜂鸣器驱动设计与验证(音乐发生器设计)

目录 一&#xff1a;章节导读 二&#xff1a;无源蜂鸣器驱动原理 三&#xff1a;PWM 发生器模块设计 3.1 PWM 发生器模块框图 3.2 PWM 发生器模块接口功能描述 3.3 PWM波生成设计文件代码 3.4 测试仿真文件 3.5 测试仿真结果 3.6 板级调试与验证之顶层文件设计 四&am…

neo4j图数据库安装和测试

neo4j图数据库安装和测试 1. 下载合适的neo4j软件版本。 https://we-yun.com/doc/neo4j/ https://neo4j.com/deployment-center/#enterprise 2. 下载JAVAJDK 由于neo4j是一个用Java编写的图形数据库&#xff0c;因此在安装和运行Neo4j之前&#xff0c;需要先安装Java Developm…

【shell漫步】1 变量定义和使用

碎碎念 转眼间已经使用了一个月的shell了&#xff0c;作为一个纯小白&#xff0c;我特别理解刚入门的时候对于linux和shell一头雾水的状态&#xff0c;尤其是打算开始学&#xff0c;但是又找不到学习的“入口函数”的那种感受。所以打算整理一下shell的骨架。shell给我的感触就…

【C#】知识点实践序列之UrlEncode在线URL网址编码、解码

欢迎来到《小5讲堂》&#xff0c;大家好&#xff0c;我是全栈小5。 这是2024年第8篇文章&#xff0c;此篇文章是C#知识点实践序列文章&#xff0c; 博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 地址编码大家应该比较经常遇到和使用到&…

记一次使用mpvue开发微信小程序动画播放播放完成再播放下一个动画,实现动画队列的实战操作

微信小程序wxss支持Css的keyframes动画&#xff0c;我们想通过事件监听&#xff0c;在动画开始、动画播放阶段、动画播放结束的时候进行下一步动作。如下图&#xff0c;有一个从右飘入&#xff0c;然后从左侧出去的动画&#xff0c;我们希望的是&#xff0c;前一个出去后&#…

微众区块链观察节点的架构和原理 | 科普时间

践行区块链公共精神&#xff0c;实现更好的公众开放与监督&#xff01;2023年12月&#xff0c;微众区块链观察节点正式面向公众开放接入功能。从开放日起&#xff0c;陆续有多个观察节点在各地运行&#xff0c;同步区块链数据&#xff0c;运行区块链浏览器观察检视数据&#xf…

STM32 内部 EEPROM 读写

STM32 的某些系列 MCU 自带 EEPROM。笔者使用的 STM32L151RET6 自带 16 KB 的 EEPROM&#xff0c;可以用来存储自定义的数据。在芯片选型时&#xff0c;自带 EEPROM 也可以作为一个考量点&#xff0c;省去了在外接 EEPROM 的烦恼。 下面简单介绍下 STM32 内部 EEPROM 的读写流…

区块链技术与应用 【全国职业院校技能大赛国赛题目解析】第一套区块链系统部署与运维

第一套区块链系统部署与运维题目 环境 : ubuntu20 fisco : 2.8.0 子任务1-2-1: 搭建区块链系统并验证 题意: 要求搭建一条四节点的区块链系统,我们选择使用fisco作为此次测试的链子 我们使用build_chain.sh进行构建单机四节点,并且使用官方的默认端口【正式比赛大概率不…

Python 操作 JMeter 探索:pymeter 实操指南

概要 JMeter 是一个流行的性能测试工具&#xff0c;用于测试 Web 应用程序的性能和负载。它通常与 GUI 一起使用&#xff0c;但如果您想在自动化测试中集成 JMeter&#xff0c;或者以编程方式创建和运行测试计划&#xff0c;那么 pymeter 库将是一个强大的工具。本文将介绍如何…

快速、准确地检测和分类病毒序列分析工具 ViralCC的介绍和详细使用方法, 附带应用脚本

介绍 viralcc是一个基因组病毒分析工具&#xff0c;可以用于快速、准确地检测和分类病毒序列。 github&#xff1a;dyxstat/ViralCC: ViralCC: leveraging metagenomic proximity-ligation to retrieve complete viral genomes (github.com) Instruction of reproducing resul…

大数据StarRocks(三) StarRocks数据表设计

1. 列式存储 1.1 列式存储方式有以下几个优点&#xff1a; 1.快速的数据查询 由于数据是按照列进行存储的&#xff0c;所以查询某个列时只需要读取该列所在的块&#xff0c;而不是整行数据&#xff0c;从而大大提高了查询效率。 2.压缩效率高 由于列式存储的数据块中只有一…

LLM Agent之再谈RAG的召回信息密度和质量

话接上文的召回多样性优化&#xff0c;多路索引的召回方案可以提供更多的潜在候选内容。但候选越多&#xff0c;如何对这些内容进行筛选和排序就变得更加重要。这一章我们唠唠召回的信息密度和质量。同样参考经典搜索和推荐框架&#xff0c;这一章对应排序重排环节&#xff0c;…