服务网关 Gateway

服务网关 Gateway

Spring Cloud Gateway 是 Spring Cloud 生态系统中的网关,它基于 Spring5.0 + SpringBoot2.0 + WebFlux(基于高性能的 Reactor 模式响应式通信框架 Netty,异步非阻塞模型)等技术开发。旨在为微服务架构提供一种简单有效的、统一的 API 路由管理方式。其目标是代替 Zuul。

Spring Cloud Gateway 不仅提供统一的路由方式(反向代理)并且基于 Filter 链的方式提供了网关基本的功能,如:鉴权、流量控制、熔断、路径重写、日志监控等。

1. 核心概念

当用户发起一个请求之后,网关会根据一定的条件匹配,匹配成功之后可以将请求转发到指定的服务地址。而在这个过程中,我们可以进行一些具体的控制(限流、日志等)。

Gateway 有三个核心概念,分别是:路由、断言、过滤器。

  • 路由(Route)

网关的基本构建块,也是网关的基础工作单元。路由由一个 ID(唯一标识)、一个目标 RUL(最终路由到的地址)、一组断言(匹配条件判断)和一组过滤器(精细化控制)构成。如果断言为 true,则匹配该路由。

  • 断言(Predicate)

用于匹配 HTTP 请求的条件,它可以基于请求的路径、方法、参数、头部信息等多个因素进行判断(类似于 Nginx 中的 location 匹配一样),如果断言与请求相匹配则路由。

  • 过滤器(Filter)

用于对请求和响应进行处理的组件,它可以用于修改请求或响应的头部信息、添加请求或响应的字段、限流、重试等多种场景。总而言之,使用过滤器能够在请求之前或之后执行业务逻辑。

首先任何请求进来,网关都会把它们拦住。根据请求的URL把它们分配到不同的路由上,路由上面会有断言,来判断请求能不能进来。进来之后会有一系列的过滤器对请求被转发前或转发后进行改动。 具体怎么个改动法,那就根据业务不同而自定义了。一般就是监控,限流,日志输出等等。

2. 执行流程

Gateway 的执行流程如下:

在这里插入图片描述

  • 网关控制器映射(Gateway Handler Mapping)

找到与请求相匹配的路由,将其发送到网关 Web 控制器。

  • 网关 Web 控制器(Gateway Web Handler)

通过指定的过滤器将请求发送到我们实际的服务执行业务逻辑,然后返回。

  • 过滤器(Filter)

主要在请求之前(鉴权、参数校验、日志记录等)和之后(修改响应头、流量监控等)做一些控制处理

Spring Cloud Gateway 的执行流程简述:

客户端向 GateWay 发出请求,然后在 GateWay Handler Mapping 中找到与请求相匹配的路由,将其发送到 GateWay Web Handler;Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(pre)或者之后(post)执行业务逻辑。

3. 入门案例

新建 gateway-9999 模块,然后在 pom.xml 文件中加入以下依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 加入上面 Eureka 客户端的相关依赖,这里就不在展示~ -->

需注意:spring-boot-starter-web 依赖需要去除,否则会报错。

写 application.yaml 配置文件,具体如下:

server:port: 9999
eureka:client:service-url:defaultZone: http://localhost:7001/eureka/instance:instance-id: gateway-9999
spring:application:name: cloud-gateway-9999cloud:gateway:routes:# 路由ID,没有固定规则但要求唯一,建议配合服务名- id: provider-8001# 匹配后提供服务的路由地址uri: http://127.0.0.1:8001# 断言predicates:# 路径相匹配的进行路由- Path=/provider/**

在启动类上面加入 @EnableEurekaClient 注解,注册到 Eureka 注册中心,从注册中心获取对应服务。

配置好之后,我们启动注册中心 Eureka7001 和提供者 8001 服务,然后启动 Gateway 服务。

通过 Postman 访问 localhost:9999/provider/get/port 或者 localhost:9999/provider/index,经测试都可以访问。

还可以使用 Java API 的方式配置路由,创建 GatewayConfig 配置类,具体如下:

@Configuration
public class GatewayConfig {@Beanpublic RouteLocator getRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();/*** 设置路由*  id: 路由ID,要求唯一*  path(): gateway访问的路径*  uri(): 实际的服务地址*/routes.route("my_route", item -> item.path("/guonei").uri("https://news.baidu.com")).build();routes.route("provider", item -> item.path("/provider/index").uri("http://127.0.0.1:8001")).build();return routes.build();}
}
4. 路由规则

一个请求在抵达网关层后,首先就要进行断言匹配,在满足所有断言之后才会进入 Filter 阶段。说白了 Predicate 就是一种路由规则,通过 Gateway 中丰富的内置断言的组合,我们就能让一个请求找到对应的 Route 来处理。

Spring Cloud GateWay 帮我们内置了很多 Predicates 功能,实现了各种路由匹配规则(通过Header、请求参数等作为条件)匹配到对应的路由。如下图所示:

在这里插入图片描述

  • DateTime 时间类断言

    利用时间断言可以实现一些类似于准点秒杀、商品限时特惠等场景。

    • After 时间点后匹配

    在该日期时间之后发生的请求都将被匹配。示例配置如下:

    spring:application:name: cloud-gateway-9999cloud:gateway:routes:- id: provider-8001uri: http://127.0.0.1:8001# 断言predicates:# 路径相匹配的进行路由# - Path=/provider/**- After=2024-01-01T12:00:32.077075700+08:00[Asia/Shanghai]
    

    配置文件中的时间参数为 UTC 时间格式,可以使用 System.out.println(ZonedDateTime.now()); 获取当前的 UTC 格式的时间。

    • Before 时间点前匹配

    在该日期时间之前发生的请求都将被匹配。示例配置如下:(下面配置代码只展示 predicates 部分~)

    predicates:- Before=2024-01-01T12:00:32.077075700+08:00[Asia/Shanghai]
    
    • Between 时间区间匹配

    有两个参数,datetime1 和 datetime2。在 datetime1 和 datetime2 之间的请求将被匹配。datetime2 参数的实际时间必须在 datetime1 之后。示例配置如下:

    predicates:- Between=2024-01-01T12:00:32.077075700+08:00[Asia/Shanghai],2024-01-02T12:00:32.077075700+08:00[Asia/Shanghai]
    
  • Cookie 类断言

验证 Cookie 中保存的信息,必须连同属性值一同验证,不能单独只验证属性是否存在。示例配置如下:

predicates:- Cookie=username,lyl

使用 Postman 进行接口测试,在 Headers 栏中加入 Key 为 Cookie,Value 为 username=lyl 的参数,然后访问对应接口。

  • Header 请求头类断言

Header 中包含了响应的属性才会被匹配,通常可以用来验证请求是否携带了访问令牌。示例配置如下:

predicates:# 请求头要有X-Request-Id属性并且值为整数的正则表达式- Header=X-Request-Id, \d+
  • Host 请求主机类断言

有一个参数:host name 列表。使用 Ant 路径匹配规则,点 . 作为分隔符。多个用逗号 , 隔开。示例配置如下:

predicates:- Host=lylhost

需要在本地 Host 文件中新增:127.0.0.1 lylhost

  • Method 请求方法类断言

HTTP 方法符合要求则匹配,例如 GET、POST 等,多个用逗号隔开,示例配置如下:

predicates:- Method=GET
  • Path 请求路径类断言

请求路径符合规则则匹配,支持正则表达式,示例配置如下:

predicates:- Path=/provider/**
  • QueryParam 请求参数类断言

验证参数,可单独验证是否包含参数,也可验证参数是否满足指定规则,符合则匹配,示例配置如下:

predicates:# 参数username符合要求则匹配- Query=username, \d+# 参数password存在则匹配- Query=password
  • RemoteAddr 远程地址类断言

远程地址符合则匹配,示例配置如下:

predicates:- RemoteAddr=192.168.1.1/24

动态路由

GateWay 支持自动从注册中心中获取服务列表并访问,即所谓的动态路由。具体配置如下:

spring:cloud:gateway:routes:- id: provider-8001# 匹配后提供服务的路由地址,lb后跟提供服务的微服务的名uri: lb://CLOUD-PROVIDER-8001predicates:- Path=/provider/**

动态路由设置时,uri 以 lb: // 开头(lb 代表从注册中心获取服务),后面是需要转发到的服务名称

分别启动 Eureka、provider-8001 和 provider-8002 服务,使用 Postman 调用 localhost:9999/provider/get/port 接口进行测试。

5. 网关过滤器

根据生命周期可以将 Spring Cloud Gateway 中的 Filter 分为 PRE 和 POST 两种:

  • PRE:代表在请求被路由之前执行该过滤器,可用来实现参数校验、权限校验、流量监控、日志输出、协议转换等功能。
  • POST:代表在请求被路由到微服务之后执行该过滤器。可用来实现响应头的修改(如添加标准的 HTTP Header )、收集统计信息和指标、将响应发送给客户端、输出日志、流量监控等功能。

根据作用范围,Filter 可以分为以下两种:

  • GatewayFilter:网关过滤器,只应用在单个路由或者一个分组的路由上。
  • GlobalFilter:全局过滤器,应用在所有的路由上。

GlobalFilter 全局过滤器是我们使用比较多的过滤器。

(1)GatewayFilter

网关过滤器(GatewayFilter)允许以某种方式修改传入的 HTTP 请求,或输出的 HTTP 响应。网关过滤器作用于特定路由。

Spring Cloud Gateway 内置了许多网关过滤器工厂来编写网关过滤器。例如:

  • AddRequestHeader:为原始请求添加 Header,参数为 Header 的名称及值
  • AddRequestParameter:为原始请求添加请求参数,参数为参数名称和值
  • AddResponseHeader:为原始响应添加 Header,参数为 Header 的名称及值
  • PrefixPath:为原始请求路径添加前缀 ,参数为前缀路径
  • RedirectTo:将原始请求重定向到指定的URL,参数为 HTTP 状态码及重定向的 URL
  • RemoveRequestHeader:为原始请求删除某个 Header,参数为 Header 名称
  • RemoveResponseHeader:为原始响应删除某个Header,参数为 Header 名称
  • SetResponseHeader:修改原始响应中某个 Header 的值,参数为 Header 名称和修改后的值
  • SetStatus:修改原始响应的状态码,参数为 HTTP 状态码,可以是数字,也可以是字符串

示例配置如下:

spring:cloud:gateway:routes:- id: provider-8001uri: lb://CLOUD-PROVIDER-8001predicates:- Path=/provider/**# 过滤器filters:# 修改原始响应的状态码- SetStatus=2024

我们也可以通过继承 AbstractGatewayFilterFactory 类,重写 shortcutFieldOrder() 方法的方式自定义网关过滤器,这里就不再展示~

(2)GlobalFilter

全局过滤器作用于所有路由,无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。

这里我们模拟一个黑名单拒绝访问的场景,具体示例代码如下:

/*** Description: 模拟实现黑名单功能* 场景:请求过来时,判断发送请求的客户端的ip,如果在黑名单中,拒绝访问*/
@Slf4j
@Component
public class BlackListFilter implements GlobalFilter, Ordered {/*** 模拟黑名单(实际场景可从数据库或Redis中查询)*/private static List<String> blackList = new ArrayList<>();static {// 模拟本机地址blackList.add("0:0:0:0:0:0:0:1");blackList.add("127.0.0.1");}/*** 过滤器核心方法* @param exchange 封装了request和response对象的上下文* @param chain    网关过滤器链(包含全局过滤器和单路由过滤器)*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取request和response对象ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();// 获取客户端IPString clientIp = request.getRemoteAddress().getHostString();// 在黑名单中则拒绝访问,直接返回if (blackList.contains(clientIp)) {response.setStatusCode(HttpStatus.UNAUTHORIZED);log.info("=====>IP:" + clientIp + " 在黑名单中,将被拒绝访问!");String data = "Request be denied!";DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());return response.writeWith(Mono.just(wrap));}// 不在黑名单的请求放行,执行后续的过滤器链return chain.filter(exchange);}/*** 返回值表示当前过滤器的顺序(优先级),数值越小,优先级越高*/@Overridepublic int getOrder() {return 0;}
}

通过 Postman 进行测试,返回 Request be denied!

6. 跨域配置

当一个请求 URL 的协议、域名、端口三者之间任意一个与当前页面 URL 不同即为跨域。

为什么会出现跨域:

出于浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

当前页面URL被请求页面URL是否跨域原因
http://www.test.com/http://www.test.com/index.html同源(协议、域名、端口号相同)
http://www.test.com/https://www.test.com/index.html协议不同(http/https)
http://www.test.com/http://www.baidu.com/主域名不同(test/baidu)
http://www.test.com/http://blog.test.com/子域名不同(www/blog)
http://www.test.com:8080/http://www.test.com:7001/端口号不同(8080/7001)

打开浏览器的 F12,当出现 ‘Access-Control-Allow-Origin’ 时,就是出现了跨域情况。

CORS

如何允许跨域,一种解决方法就是目的域告诉请求者允许什么来源域来请求,那么浏览器就会知道 B 域是否允许 A 域发起请求。

CORS(Cross-origin resource sharing),跨域资源共享就是这样一种解决手段。

CORS 使得浏览器在向目的域发起请求之前先发起一个 OPTIONS 方式的请求到目的域获取目的域的信息,比如获取目的域允许什么域来请求的信息。具体配置如下:

spring:cloud:gateway:globalcors:cors-configurations:'[/**]':allowCredentials: trueallowedOriginPatterns: "*"allowedMethods: "*"allowedHeaders: "*"add-to-simple-url-handler-mapping: true
7. JWT

JWT(JSON Web Token)是一种用于双方之间传递安全信息的简洁的、URL 安全的声明规范。定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 对象的形式安全的传递信息。特别适用于分布式站点的单点登录(SSO)场景。

JWT 的原理就是,服务器在用户登录认证之后,生成一个 JSON 对象,然后生成一个长字符串返回给用户。用户在后面发起请求时,都会在请求头中携带 JTW,服务器对其进行验证,解析成功即让其成功访问,反之则拒绝访问。

JWT 是一个很长的字符串,中间用点.分割成 3 部分,示例如下:

eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSm9obiIsImFkbWluIjp0cnVlfQ.1YiYlxYX9I1Yjdk0lyJp3vluWfbOSsGToWzMDJcPcOpnbEVZZGzR4NhpgYFKqmAzarsfnNpOKrvS48KeXuO0IA

  • Header(头部)

JSON对象,描述 JWT 的元数据。

Header 通常包含两个部分,即 token 的类型(typ)和算法(alg)。

其中 alg 属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ 属性表示这个令牌(token)的类型(type),统一写为 JWT。示例如下:

{"alg": "HS512","typ": "JWT"
}

Header 由 Base64 编码后构成了 JWT 的第一部分。

Base64 是一种用 64 个字符来表示任意二进制数据的方法,Base64 是一种任意二进制到文本字符串的编码方法,常用于在 URL、Cookie、网页中传输少量二进制数据。

  • Payload(载荷)

    Payload 是 JWT 的第二部分,它包含了要传递的信息,也就是所谓的 claim,有三种类型:

    • 预定义的声明(Registered Claims)

      这些声明是可选的,但建议尽可能使用。

      • iss:签发者
      • sub: 主题
      • aud:接收者
      • exp:过期时间,必须要大于签发时间
      • nbf:生效时间
      • iat:签发时间
      • jti:编号,唯一身份标识
    • 自定义的声明(Public Claims)

    自定义公共的声明,用于传递用户的信息或其他数据,建议使用命名空间来避免冲突。

    • 私有的声明(Private Claims)

    在双方约定的情况下私下使用的声明,避免和其他声明冲突。

    示例如下:

    {"sub":"GE_ecd48edee025487897926cdd1e71234","name":"用户名","created":1704092559000,"exp":1704178959
    }
    

    Payload 也是由 Base64 编码后与 Header 通过一个点号连接,形成了 JWT 的第二部分。

  • Signature(签证)

Signature 是 JWT 的第三部分,由 Header 和 Payload 经过 base64UrlEncode 之后,指定一个密钥(secret)通过算法计算得出,算法通常是 HS256(HMACSHA256)或RS256(RSASHA256)等。

HMACSHA512(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

JWT 的签名过程如下:

1)取得 Header 和 Payload 的 Base64Url 编码后的字符串,中间用点号连接起来。

2)使用 Header 中指定的算法和密钥对上一步骤得到的字符串进行签名,生成 Signature。

3)将 Header、Payload 和 Signature 以点号连接起来,形成最终的 JWT。

在验证 JWT 时,需要对 Header 和 Payload 进行 Base64Url解码,再按照相同的算法和密钥计算Signature,与JWT中的Signature进行比对,如果一致说明JWT是真实的,否则说明JWT可能被篡改过。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker篇】使用Docker操作镜像

文章目录 &#x1f6f8;镜像&#x1f33a;基本操作⭐docker --help⭐docker pull [ 参数 ]⭐docker images⭐docker save -- 导出⭐docker rmi -- 删除⭐docker load -- 导入 &#x1f6f8;镜像 镜像是指在计算机领域中&#xff0c;通过复制和创建一个与原始对象相似的副本的过…

学习JavaEE的日子 day11 初识面相对象

day11 1.初识面相对象 1.1 类和对象的理解 类 * 类是对象的数据类型&#xff0c;类是具有相同属性和行为的一组对象的集合 * 简单理解&#xff1a;类就是对现实事物的一种描述 类的组成 * 属性&#xff1a;指事物的特征&#xff0c;例如&#xff1a;手机事物&#xff08;品牌…

Postgresql 12.2 + PostGIS 3.0.1 安装部署

参考文档&#xff1a; 按照该文档安装即可&#xff0c;如果遇到报错&#xff0c;可以参考下文&#xff1a; https://blog.csdn.net/weixin_41166785/article/details/127674169 所需的安装包 在资源里面&#xff08;我看下怎么可以不用积分下载&#xff09; 1、no acceptable…

windows安装RabbitMq,修改数据保存位置

1、先安装Erlang&#xff0c; Erlang和RabbitMQ有版本对应关系。 官网RabbitMQ与Erlang版本对应RabbitMQ Erlang Version Requirements — RabbitMQ 2、安装RabbitMQ。 3、修改数据保存地址。找到安装目录下的sbin文件夹&#xff0c;找到rabbitmq-env.bat&#xff0c;编辑文件…

Nacos入门到精通

Nacos概述&#xff1a; 全称Dynamic Naming and Configuration Service&#xff0c;是一个Nacos&#xff0c;全称Dynamic Naming and Configuration Service&#xff0c;是一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台。其核心功能主要包括服务发现、健康检查…

Flink启动Yarn Session报错:Couldn‘t deploy Yarn session cluster

Flink版本&#xff1a;1.1.3 启动Yarn Session的语句&#xff1a;bin/yarn-session.sh -nm test -d 报错截图如下&#xff1a; 仅通过ERROR信息只能知道是yarn session集群未能正常启动&#xff0c;因此继续向下查找&#xff1a; 找到报错信息的Caused by部分&#xff1a; 报…

基于vue+Spring Boot家政服务人员预约系统iph9d

通过对家政服务管理内容的学习研究&#xff0c;进而设计并实现一个家政服务系统。系统能实现的主要功能应包括即时通讯、通讯回复、预约订单、接单信息、服务费用管、服务评价的一些操作。还有可以正确的为用户服务&#xff0c;准确显示当前信息[5]。 开发软件有很多种可以用&…

AI工具(20240116):Copilot Pro,Fitten Code等

Copilot Pro Copilot Pro是微软推出的Copilot的付费增强版本,通过提供优先访问GPT-4等最新AI模型,大大提升用户的创造力和工作效率。该服务可与Microsoft 365订阅捆绑使用,支持在Word、Excel等Office应用内直接使用Copilot功能,帮助用户更快速地起草文档、电子邮件和演示文稿等…

Linux 入门命令大全汇总 + Linux 集锦大全 【20240115】

文章目录 Linux 入门命令大全汇总Linux 集锦大全更多信息 Linux 入门命令大全汇总 别有一番风趣的alias 刚刚好合适的 apropos 命令 迷你计算器 bc 可看黄道吉日的 cal 全文可查看&#xff1a; Linux入门命令大全全文 Linux 集锦大全 linux终端中最漂亮的几款字体介绍及…

OpenCV——多分辨率LBP的计算方法

目录 一、算法原理1、原理概述2、参考文献 二、代码实现三、结果展示 OpenCV——多分辨率LBP的计算方法由CSDN点云侠原创&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫。 一、算法原理 1、原理概述 基本LBP算子虽然在早期…

快速入门Java NIO(Not I/O)的网络通信框架--Netty

Netty 入门 了解netty前需要对nio有一定认识,该笔记基础来自bilinbili黑马,在此基础上自己学习的笔记,添加了一些自己的理解 了解java 非阻塞io编程 1. 概述 1.1 Netty 是什么&#xff1f; Netty is an asynchronous event-driven network application framework for rapid …

23/76-LeNet

LeNet 早期成功的神经网络。 先使用卷积层来学习图片空间信息。 然后使用全连接层转换到类别空间。 #In[]LeNet,上世纪80年代的产物,最初为了手写识别设计from d2l import torch as d2l import torch from torch import nn from torch.nn.modules.loss import CrossEntropyLos…

Vue实战:两种方式创建Vue项目

文章目录 一、实战概述二、实战步骤&#xff08;一&#xff09;安装Vue CLI脚手架1、从Node.js官网下载LTS版本2、安装Node.js到指定目录3、配置Node.js环境变量4、查看node版本5、查看npm版本6、安装Vue Cli脚手架7、查看Vue Cli版本 &#xff08;二&#xff09;命令行方式构建…

Python多线程爬虫——数据分析项目实战详解

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 ChatGPT体验地址 文章目录 前言爬虫获取cookie网站爬取与启动CSDN爬虫爬虫启动将爬取内容存到文件中 多线程爬虫选择要爬取的用户 线程池 爬虫 爬虫是指一种自动化程序&#xff0c;能够模…

Jmeter 测试脚本录制器-HTTP 代理服务器

Jmeter 测试脚本录制器-HTTP 代理服务器 Jmeter 配置代理服务器代理服务器获取请求地址示例图配置步骤 浏览器配置代理Google 浏览器插件配置代理windows 本地网络配置代理 启动录制&#xff0c;生成证书生成证书导入证书Jmeter 配置证书 浏览器点击页面&#xff0c;录制请求地…

【深度学习】RTX2060 2080如何安装CUDA,如何使用onnx runtime

文章目录 如何在Python环境下配置RTX 2060与CUDA 101. 安装最新的NVIDIA显卡驱动2. 使用conda安装CUDA Toolkit3. 验证onnxruntime与CUDA版本4. 验证ONNX需求版本5. 安装ONNX与onnxruntime6. 编写ONNX推理代码 如何在Python环境下配置RTX 2060与CUDA 10 RTX 2060虽然是一款较早…

AI嵌入式K210项目(11)-SPI Flash读写

文章目录 前言一、K210的SPI二、Flash介绍三、实验过程总结 前言 这一章我们来学习下SPI及其应用&#xff0c;SPI 是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;由于其高速、同步和简单的特性&#xff0c;被广泛应用于各种微控制器和外围设备之间的通…

微信小程序防止截屏录屏

一、使用css添加水印 使用微信小程序原生的view和css给屏幕添加水印这样可以防止用户将小程序内的隐私数据进行截图或者录屏分享导致信息泄露&#xff0c;给小程序添加一个水印浮层。这样即使被截图或者拍照&#xff0c;也能轻松地确定泄露的源头。效果图如下&#xff1a; 代码…

MongoDB认证考试小题库

Free MongoDB C100DBA Exam Actual Questions 关于MongoDB C100 DBA 考试真题知识点零散整理 分片架构 应用程序 --> mongos --> 多个mongod对于应用来说&#xff0c;连接分片集群跟连接一台单机mongod服务器一样分片好处&#xff0c; 增加可用RAM、增加可用磁盘空间、…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(3)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…