Spring Cloud之API网关(Zuul)

news2024/11/19 3:31:48

目录

Zuul

简介

功能

工作流程

搭建

1.引入依赖

2.添加注解

3.路由转发

4.测试

实现原理

@EnableZuulProxy注解

ZuulServlet

FilterProcessor

Zuul内置过滤器

常用配置


Zuul

简介

        zuul是SpringCloud子项目的核心组件之一,可以作为微服务架构中的API网关使用,支持动态路由和过滤功能;

功能

1.统一入口:为全部服务提供一个唯一的入口,网关起到了外部和内部的隔离作用

2.鉴权校验:识别每一个请求的权限,拒绝不符合要求的请求

3.动态路由:动态的将请求路由到不同的后端集群中

4.减少客户端与服务器端的耦合:服务可以独立发展,通过网关来进行映射

工作流程

Zuul本质是一个Servlet来对请求进行控制,核心是创建了一系列的过滤器。Zuul包括以下四种过滤器:       

        1、PRE过滤器:请求路由到具体的服务之前执行,可以用作安全校验、身份校验、参数校验等前置工作;

        2、ROUTING过滤器:用于将请求路由到具体的服务实例,默认使用Http Client进行网络请求;

        3、POST过滤器:在请求已经被路由到微服务后执行,通常用于收集统计信息、指标并将响应返回给客户端;

        4、ERROR过滤器:在其他过滤器出现异常时执行;

各个类型的过滤器执行顺序依次为PRE过滤器->ROUTING过滤器->POST过滤器,如果出现异常就执行ERROR过滤器

搭建

1.引入依赖

        <dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
	
		<!-- zuul 依赖 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
		</dependency>

2.添加注解

启动类添加注解 @EnableZuulProxy

@SpringBootApplication
 @EnableZuulProxy        //开启Zuul
 @EnableEurekaClient
 public class ZuulMain9401 {
     public static void main(String[] args) {
         SpringApplication.run(ZuulMain9401.class, args);
     }
 }

        因为不涉及服务消费等,只是做api的处理,所以主启动类还是比较简单的

3.路由转发

1.在原有的application.yml配置文件上添加:

 zuul:
   routes:
     user-a:
       path: /api-a/**
       serviceId: eureka-provide

user-a:随便定义

path:外部访问路径

serviceId:微服务配置文件的spring.application.name 的值

2.设置url

 zuul:
   routes:
 #    user-a:
 #      path: /api-a/**
 #      serviceId: eureka-provide
     user-b:
       path: /api-b/**
       url: http://localhost:7101/

url:需要转发到哪个服务

3.设置非注册Eureka的服务id

        通过Ribbon设置访问一些没有注册进Eureka的服务,同样在API网关也能通过配置文件设置Ribbon来达到一样的效果

 zuul:
   routes:
 #    user-a:
 #      path: /api-a/**
 #      serviceId: eureka-provide
 #    user-b:
 #      path: /api-b/**
 #      url: http://localhost:7101/
     user-c:
       path: /api-c/**
       serviceId: provide-without-eureka
 ​
 #一定需要这个才行
 ribbon:
   eureka:
     enabled: false
 provide-without-eureka:
   ribbon:
     ServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
     listOfServers: localhost:7201, localhost:7202
     ConnectTimeout: 1000
     ReadTimeout: 3000
     MaxTotalHttpConnections: 500
     MaxConnectionsPerHost: 100

serviceId同样是微服务的名称,然后对这个微服务设置,所以是设置微服务名[provid-without-eureka].ribbon

4.测试

接着访问http://localhost:8080/api-a/eureka/provide,按照分析,应该会被转发到eureka-provide 服务里的eureka/provide路径。

实现原理

@EnableZuulProxy注解

        zuul的使用比较简单,只需要在启动类上添加@EnableZuulProxy注解即可,zuul所有的功能都是围绕改注解进行,@EnableZuulProxy的作用是加载ZuulProxyMarkerConfiguration的实例:

@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {

}

ZuulProxyMarkerConfiguration的作用是注入一个ZuulProxy的标记实例

@Configuration
public class ZuulProxyMarkerConfiguration {
    @Bean
    public Marker zuulProxyMarkerBean() {
        return new Marker();
    }

    class Marker {
    }
}

内部类Marker唯一的作用就是用于标记,所以需要看哪里需要用到该标记,通过引用搜索发现引用的地方是ZuulProxyAutoConfiguration,父类是ZuulServerAutoConfiguration

@Configuration
@EnableConfigurationProperties({ ZuulProperties.class })
@ConditionalOnClass(ZuulServlet.class)
@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)
// Make sure to get the ServerProperties from the same place as a normal web app would
// FIXME @Import(ServerPropertiesAutoConfiguration.class)
public class ZuulServerAutoConfiguration {

父类ZuulServerAutoConfiguration中会向Spring容器中注入ServletRegistrationBean实例,该实例中创建了一个ZuulServlet。而Zuul的核心功能就在于这个ZuulServlet,Zuul接收到的所有请求最终都会由于ZuulServlet的service方法来完成

@Bean
    @ConditionalOnMissingBean(name = "zuulServlet")
    public ServletRegistrationBean zuulServlet() {
        ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean<>(new ZuulServlet(),
                this.zuulProperties.getServletPattern());
        // The whole point of exposing this servlet is to provide a route that doesn't
        // buffer requests.
        servlet.addInitParameter("buffer-requests", "false");
        return servlet;
    }

ZuulServlet

ZuulServlet继承之HttpServlet,初始化init方法创建了ZuulRunner对象,而核心功能在于service方法,所有请求都会先执行到service方法

@Override
    public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
        try {
            /** 1.初始化ZuulRunner 对象*/
            init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
            /** 2.获取HttpRequest请求上下文*/
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();

            try {
                /** 3.执行pre过滤器*/
                preRoute();
            } catch (ZuulException e) {
                /** 异常时执行error过滤器和post过滤器*/
                error(e);
                postRoute();
                return;
            }
            try {
                /** 4.执行route过滤器*/
                route();
            } catch (ZuulException e) {
                /** 异常时执行error过滤器和post过滤器*/
                error(e);
                postRoute();
                return;
            }
            try {
                /** 5.执行post过滤器*/
                postRoute();
            } catch (ZuulException e) {
                /** 异常时执行error过滤器*/
                error(e);
                return;
            }

        } catch (Throwable e) {
            error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
        } finally {
            /** 清理本地缓存RequestContext*/
            RequestContext.getCurrentContext().unset();
        }
    }

FilterProcessor

        FilterProcessor是过滤器的具体执行者,是一个单例对象。ZuulServlet的各种过滤器最终分别执行了FilterProcessor的preRoute()、route()、postRoute()、error()方法,而这四个方法最终都是执行了FilterProcessor的内部方法runFilters(String filterType)方法。

public Object runFilters(String sType) throws Throwable {
        if (RequestContext.getCurrentContext().debugRouting()) {
            Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
        }
        boolean bResult = false;
        /** 1.获取指定类型的过滤器列表*/
        List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                ZuulFilter zuulFilter = list.get(i);
                /** 2.遍历执行过滤器*/
                Object result = processZuulFilter(zuulFilter);
                if (result != null && result instanceof Boolean) {
                    bResult |= ((Boolean) result);
                }
            }
        }
        return bResult;
    }

Zuul内置过滤器

        Zuul过滤器可以通过自定义ZuulFilter实现类来添加,同时Zuul还提供了内置的众多过滤器,分别如下图示,比较核心的就是RibbonRoutingFilter,这个过滤器负载路由转发并且集成了Ribbon的负载均衡功能:

        Zuul本质上就是一个Servlet,并且通过Spring容器管理了一系列的过滤器ZuulFilter实例,各个ZuulFilter有一个类型,包括preRoute、route、postRoute、error四种类型,不同的类型执行的顺序和时机不同。当请求进入Zuul时,由ZuulServlet接收并通过service方法处理。service方法逻辑就是从Spring容器中找到各种类型的ZuulFilter过滤器实例,然后遍历按顺序和时机来执行过滤器的处理逻辑。使用时可以自定义ZuulFilter来对请求的不同时间短进行功能扩展。

常用配置

zuul:
  #给服务配置路由
  routes:
    user-service:
      path: /userService/**
    feign-service:
      path: /feignService/**
  #关闭默认路由配置
  ignored-services: user-service,feign-service
  #给网关路由添加前缀
  prefix: /proxy
  #配置过滤敏感的请求头信息,设置为空就不会过滤
  sensitive-headers: Cookie,Set-Cookie,Authorization
  #设置为true重定向是会添加host请求头
  add-host-header: true
  # 关闭重试机制
  retryable: true
  PreLogFilter:
    pre:
      #控制是否启用过滤器
      disable: false

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MappingMongoConverter原生mongo 枚举类ENUM映射使用的是name

j.l.IllegalArgumentException: No enum constant com.xxx.valobj.TypeEnum.stringat java.lang.Enum.valueOf

dracut添加指定固件

文章目录 linux-firmware1、固件介绍2、Microcode updates for CPUs3、如何添加固件 linux-firmware 1、固件介绍 存放在 /lib/firmware&#xff0c;固件来自kernel 仓库更多的固件可以参考git仓库&#xff0c;https://git.kernel.org/pub/scm/linux/kernel/git/firmware/lin…

day16_IO

今日内容 1.复习 2.IO 3.Hutool 4.Idea会导jar包 一、File[熟悉] 1.1 介绍 文件和目录(文件夹) 路径名的抽象表示形式。 即使用路径来表示一个文件或者一个文件夹对象 路径: 相对路径,相对于当前项目的项目名下绝对路径,按照磁盘来确定 1.2 构造方法 File(String pathname) 通…

从 Hash索引、二叉树、B-Tree 与 B+Tree 对比看索引结构选择

从 Hash索引、二叉树、B-Tree 与 BTree 对比看索引结构选择 1、Hash 结构1.1、关于 Hash 数据结构1.2、InnoDB索引为啥不选 Hash 结构1.3、关于InnoDB 提供自适应 Hash 索引 &#xff08;Adaptive Hash Index&#xff09; 2、二叉搜索树3、平衡二叉树&#xff08;AVL树 &#x…

EMQX内置Web管理控制台-Dashboard

一、Dashboard概述 EMQX Dashboard官网文档&#xff1a;https://docs.emqx.com/zh/enterprise/v5.1/dashboard/introduction.html 1、简介 EMQX 为用户提供了一个功能强大的内置管理控制台&#xff0c;即 EMQX Dashboard。通过这个控制台的 Web 界面&#xff0c;用户可以轻松监…

基于STM32闭环步进电机控制系统设计

**单片机设计介绍&#xff0c;1654基于STM32闭环步进电机控制系统设计&#xff08;仿真&#xff0c;程序&#xff0c;说明&#xff09; 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序文档 六、 文章目录 一 概要 基于STM32的闭环步进电机控制系统设计是…

劳动安全无小事,劳保安全鞋为您的足部安全保驾护航

安全生产责任重于泰山。日常说到劳动防护&#xff0c;人们往往先想到的是安全帽、工作服、安全带等身体与头部的防护&#xff0c;从而足部的伤害是较容易被人们所忽视的。其实脚部的防护至关重要&#xff0c;我们在日常工作中常见的足部伤害有&#xff1a;冲击、撞击伤害&#…

CSS中的栅格布局

CSS中的栅格布局 在写前端项目的时候&#xff0c;我之前一直习惯使用flex布局&#xff0c;flex布局写起来比较随心&#xff0c;几乎可以实现任意形式的页面布局。不过自从B占看到某位大佬的grid布局后&#xff0c;发现布局居然还可以这么玩&#xff0c;正好自己在写一个vue3的…

中兴再推爆款,双2.5G网口的巡天AX3000Pro+仅需299元

10月30日消息,中兴新款路由器中兴巡天AX3000Pro将于10月31日20:00正式开售,当前可在天猫、京东及红魔商城进行预约,首发价格299元。 据了解,中兴巡天AX3000Pro是中兴智慧家庭推出的巡天系列新品,也是当前市场上唯一一款300元价位内配备双2.5G网口的路由器。 中兴巡天AX3000Pro…

客户端与服务端实时通讯(轮询、websocket、SSE)

客户端与服务端实时通讯 背景 在某些项目中&#xff0c;某些数据需要展示最新的&#xff0c;实时的&#xff0c;这时候就需要和服务端进行长时间通讯 方案 对于数据实时获取&#xff0c;我们一般会有4种方案&#xff1a; 1.短轮询&#xff1a;使用浏览器的定时器发起http请…

三叠云督察督办解决方案:助力企业高效决策与执行

信息时代的到来&#xff0c;企业面临着日益增长的管理挑战。高竞争的商业环境中&#xff0c;如何实现高效的决策和执行成为了企业迫切需要解决的问题。在现代企业管理中&#xff0c;督察督办工作的重要性也日益凸显。 然而&#xff0c;传统的督察督办模式存在诸多问题&#xff…

JavaScript组合模式

JavaScript组合模式 1 什么是组合模式2 宏命令3 示例&#xff1a;扫描文件夹4 引用父对象 1 什么是组合模式 组合模式是一种结构型设计模式&#xff0c;用于将对象组合成树形结构&#xff0c;并使客户端能够统一处理单个对象和组合对象。它通过使用继承和组合两个概念&#xf…

题目描述:输入数字,第一行为数组的大小,第二行为数组的值。求其中相邻两个数字相差不大于8的最大片段的长度。

题目描述&#xff1a; 输入数字&#xff0c;第一行为数组的大小&#xff0c;第二行为数组的值。求其中相邻两个数字相差不大于8的最大片段的长度。 示例1&#xff1a; 输入&#xff1a;91 2 4 6 12 2 8 6 4 输出&#xff1a;5示例2&#xff1a; 输入&#xff1a;101 4 5 6 2…

数据清洗(1)--数据查缺补漏

前言 之前使用scikit 进行一些基础模型的选择&#xff08;SVM支持向量机&#xff0c;LR算法&#xff0c;KNN&#xff0c;SGD&#xff0c;Bays贝叶斯&#xff0c;决策树&#xff0c;随机森林&#xff09;&#xff0c;创建&#xff0c;训练&#xff08;测试集验证集&#xff09;…

Redis测试新手入门教程

在测试过程中&#xff0c;我们或多或少会接触到Redis&#xff0c;今天就把在小破站看到的三丰老师课程&#xff0c;把笔记整理了下&#xff0c;用来备忘&#xff0c;也希望能给大家带来亿点点收获。 主要分为两个部分&#xff1a; 一、缓存技术在后端架构中是如何应用的&#…

C语言实现求某班学生的平均成绩和均方差

完整代码&#xff1a; /* 已知求成绩的平均值和均方差公式为&#xff1a;&#x1d44e;&#x1d463;&#x1d452; ∑&#x1d460;&#x1d456;/n , &#x1d451;&#x1d452;&#x1d463; √(∑ (&#x1d460;&#x1d456;−&#x1d44e;&#x1d463;&#x1d45…

Android开发知识学习——HTTPS

文章目录 定义HTTPS连接HTTPS 连接建立的过程课后题 定义 HTTP Secure / HTTP over SSL / HTTP over TLS SSL&#xff1a;Secure Socket Layer -> TLS Transport Layer Security 定义&#xff1a;在HTTP之下增加的一个安全层&#xff0c;用于保障HTTP的加密传输 本质&…

Python 自动化测试全攻略:五种自动化测试模型实战详解!

随着移动互联网的发展&#xff0c;软件研发模型逐步完善&#xff0c;软件交付质量越来越受到软件公司的重视&#xff0c;软件测试技术特别是自动化测试技术开始在软件系统研发过程中发挥着越来越重要的作用。 与传统的手工测试技术相比&#xff0c;自动化测试具备了良好的可操…

Mysql进阶-索引篇(下)

SQL性能分析 SQL执行频率 MySQL 客户端连接成功后&#xff0c;通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令&#xff0c;可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次&#xff0c;通过sql语句的访问频次&#xff0c;我们可…