深入探索Spring Cloud Gateway:微服务网关的最佳实践

news2024/11/24 14:42:19

优质博文:IT-BLOG-CN

Spring Cloud Gateway作为Spring Cloud框架的第二代网关,在功能上要比Zuul更加的强大,性能也更好。随着Spring Cloud的版本迭代,Spring Cloud官方有打算弃用Zuul的意思。在笔者调用了Spring Cloud Gateway的使用和功能上,Spring Cloud Gateway替换掉Zuul的成本上是非常低的,几乎可以无缝切换。Spring Cloud Gateway几乎包含了Zuul的所有功能。

一、网关定义

API网关是一个反向路由,屏蔽内部细节,为调用者提供统一入口,接收所有调用者请求,通过路由机制转发到服务实例。API网关是一组“过滤器Filter”集合,可以实现一系列与核心业务无关的横切面功能,如安全认证、限流熔断、日志监控

网关在系统中所处的位置:

二、快速开始

网关启动步骤(代码演示):

【1】添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

【2】配置文件

spring:
  cloud:
    gateway:
      discovery: # 启用通过服务发现自动创建路由。
        locator:
          enabled: true
      routes:
        - id: example_route   #路由ID,根据业务自行定义
          uri: lb://example-service  #目标服务的地址,这里使用 lb:// 前缀来表示负载均衡。可以是 HTTP(s) URI 或其他协议的 URI - http://bin.org:80/get。
          predicates:
            - Path=/example/** #predicates: 谓词数组,用于匹配请求。常见的谓词包括 Path、Method、Header 等。
          filters:   #过滤器数组,用于在请求被转发到目标服务之前和之后进行处理。常见的过滤器包括 AddRequestHeader、StripPrefix、RewritePath 等。
            - AddRequestHeader=X-Example, ExampleValue #过滤器会在请求头中添加 X-Example,值为 ExampleValue。
            - StripPrefix=1 #过滤器会移除路径中的第一个前缀。例如,请求路径 /example/test 会变成 /test。
        - id: rate_limited_route
          uri: http://ratelimited.org
          predicates:
            - Path=/ratelimited/**
          filters:
            - RequestRateLimiter=redis-rate-limiter # 限流:通过 RequestRateLimiter 过滤器实现
        - id: retry_route
          uri: http://retry.org
          predicates:
            - Path=/retry/**
          filters:
            - Retry=5 #重试:通过 Retry 过滤器实现。
      default-filters: #default-filters 是全局过滤器数组,适用于所有路由。这个过滤器会在所有响应中添加 X-Response-Default 头,值为 Default。
        - AddResponseHeader=X-Response-Default, Default
      globalcors: #globalcors 用于配置全局的 CORS(跨域资源共享)设置。
        corsConfigurations: #corsConfigurations: 定义 CORS 配置的路径模式。
          '[/**]': #匹配所有路径。
            allowedOrigins: "*" #允许的源,* 表示允许所有源。
            allowedMethods: #允许的 HTTP 方法,包括 GET、POST、DELETE 和 PUT。
              - GET
              - POST
              - DELETE
              - PUT

三、Spring Cloud GateWay 架构图

客户端向Spring Cloud Gateway发出请求。 在Gateway Handler Mapping中找到请求相对匹配路由(这个时候就用到predicate),则将其发送到Gateway web handler处理。 handler处理请求时会经过一系列的过滤器链。 过滤器链被虚线划分的原因是过滤器链可以在发送代理请求之前或之后执行过滤逻辑。 先执行所有pre过滤器逻辑,然后进行代理请求。 在发出代理请求之后,收到代理服务的响应之后执行post过滤器逻辑。这跟Zuul的处理过程很类似。在执行所有pre过滤器逻辑时,往往进行了鉴权、限流、日志输出等功能,以及请求头的更改、协议的转换;转发之后收到响应之后,会执行所有post过滤器的逻辑,在这里可以响应数据进行了修改,比如响应头、协议的转换等。在上面的处理过程中,有一个重要的点就是将请求和路由进行匹配,这时候就需要用到predicate,它是决定了一个请求走哪一个路由。

四、SpringColoud GateWay 核心组件

集合上面的配置和架构图进行说明

【1】Route路由: Gateway的基本构建模块,它由ID、目标URL、断言集合和过滤器集合组成。如果聚合断言结果为真,则匹配到该路由。

Route路由-动态路由实现原理: 配置变化Apollo + 服务地址实例变化NacosSpring Cloud Gateway通过RouteDefinitionLocatorRouteRefreshListener等组件实现动态路由。

先看下配置信息,方便后面原理的理解:SpringCloudGateway bootstrap.yml的配置如下:

spring:
  application:
    name: gateway-service
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER_ADDR:localhost:8848}
    apollo:
      bootstrap:
        enabled: true
      meta: ${APOLLO_META:localhost:8080}

application.yml的配置如下:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
apollo:
  bootstrap:
    namespaces: application # 1、登录 Apollo 控制台。 2、创建一个新的配置,例如 application.yml。 3、内容就是上看配置的SpringCloud Gateway 配置的路由信息

1、RouteDefinitionLocatorSpring Cloud Gateway启动时,会通过RouteDefinitionLocatorApollo加载初始的路由定义。
2、DiscoveryClientRouteDefinitionLocator:使用Nacos进行服务发现,从Nacos获取动态路由定义。
3、RouteDefinitionRepository:加载的路由定义会存储在RouteDefinitionRepository中,供后续路由匹配使用。
4、RouteRefreshListener:监听路由定义的变化事件(如配置更新、服务实例变化等)。当监听到路由定义变化事件时,触发路由刷新操作,更新网关的路由规则,重新加载并应用新的路由配置。

GatewayHandlerMapping根据预先配置的路由信息和请求的属性(如路径、方法、头部信息等)来确定哪个路由与请求匹配。它使用谓词Predicates来进行匹配判断。

【2】Predicate断言: 这是一个Java 8 Function Predicate。输入类型是Spring Framework ServerWebExchange。允许开发人员匹配来自HTTP请求的任何内容,例如Header或参数。Predicate接受一个输入参数,返回一个布尔值结果。Spring Cloud Gateway内置了许多Predict,这些Predict的源码在org.springframework.cloud.gateway.handler.predicate包中,如果读者有兴趣可以阅读一下。现在列举各种 Predicate如下图:

在上图中,有很多类型的Predicate,比如说时间类型的 Predicated[AfterRoutePredicateFactory BeforeRoutePredicateFactory BetweenRoutePredicateFactory],当只有满足特定时间要求的请求会进入到此Predicate中,并交由Router处理;Cookie类型的CookieRoutePredicateFactory,指定的Cookie满足正则匹配,才会进入此Router。以及hostmethodpathquerparamremoteaddr类型的Predicate,每一种Predicate都会对当前的客户端请求进行判断,是否满足当前的要求,如果满足则交给当前请求处理。如果有很多个Predicate,并且一个请求满足多个Predicate,则按照配置的顺序第一个生效。

Predicate 断言配置:

server:
  port: 8080
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: gateway-service
          uri: https://www.baidu.com
          order: 0
          predicates:
            - After=2017-01-20T17:42:47.789-07:00[America/Denver]
            - Host=**.foo.org
            - Path=/headers
            - Method=GET
            - Header=X-Request-Id, \d+
            - Query=foo, ba.
            - Query=baz
            - Cookie=chocolate, ch.p

在上面的配置文件中,配置了服务的端口为8080,配置spring cloud gateway相关的配置,id标签配置的是routerid,每个router都需要一个唯一的iduri配置的是将请求路由到哪里,本案例全部路由到https://www.baidu.com

Predicates After=2017-01-20T17:42:47.789-07:00[America/Denver] 会被解析成PredicateDefinition对象name =After ,args= 2017-01-20T17:42:47.789-07:00[America/Denver]。需要注意的是PredicatesAfter这个配置,遵循契约大于配置的思想,它实际被 AfterRoutePredicateFactory这个类所处理,这个After就是指定了它的Gateway web handler类为AfterRoutePredicateFactory,同理,其他类型的Predicate也遵循这个规则。当请求的时间在这个配置的时间之后,请求会被路由到指定的URL。跟时间相关的Predicates还有 Before Route Predicate FactoryBetween Route Predicate Factory,读者可以自行查阅官方文档,再次不再演示。

Query=baz Query的值以键值对的方式进行配置,这样在请求过来时会对属性值和正则进行匹配,匹配上才会走路由。经过测试发现只要请求汇总带有baz参数即会匹配路由[localhost:8080?baz=x&id=2],不带baz参数则不会匹配。

Query=foo, ba.:这样只要当请求中包含foo属性并且参数值是以 ba开头的长度为三位的字符串才会进行匹配和路由。使用curl测试,命令行输入:curl localhost:8080?foo=bab测试可以返回页面代码,将foo的属性值改为babx再次访问就会报404,证明路由需要匹配正则表达式才会进行路由。

Header=X-Request-Id, \d+:使用curl测试,命令行输入:curl http://localhost:8080 -H "X-Request-Id:88" 则返回页面代码证明匹配成功。将参数-H "X-Request-Id:88"改为-H "X-Request-Id:spring"再次执行时返回404证明没有匹配。

【3】Filter过滤器:方案一:写死在代码中

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        //openapi路由转发
        .route("openapi_route", p -> p.path( "/openapi/**").filters(f->f.removeRequestHeader("Expect"))
        .uri("lb://order-openapi-service"))
        .build();
}

方案二:配置文件yml

# gateway 的配置形式
 routes:
  - id: order-service #路由ID,没有规定规则但要求唯一,建议配合服务名。
    uri: lb://order-service
    predicates:
      - Path=/order/**
    filters:
      - ValidateCodeGatewayFilter

Filter过滤器:Filter按处理顺序Pre Filter / Post Filter

Filter按作用范围分为: GlobalFilter全局过滤器。GatewayFilter 指定路由的过滤器。
Filter过滤器-扩展自定义Filter Filter支持通过spi扩展。实现GatewayFilterOrdered接口。
Filter方法: 过滤器处理逻辑。getOrder:定义优先级,值越大优先级越低。

全局过滤器示例: 创建一个全局过滤器类,实现GlobalFilter接口:

public class TokenFilter implements GlobalFilter, Ordered {

    Logger logger=LoggerFactory.getLogger( TokenFilter.class );
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.isEmpty()) {
            logger.info( "token is empty..." );
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
      // // 过滤器的执行顺序,值越小优先级越高
        return -100;
    }
}

自定义路由过滤器示例: 创建自定义的路由过滤器,可以实现GatewayFilter接口:

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyCustomFilter extends AbstractGatewayFilterFactory<MyCustomFilter.Config> {

    public MyCustomFilter() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 前置过滤逻辑
            System.out.println("Custom Pre Filter executed");
            
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                // 后置过滤逻辑
                System.out.println("Custom Post Filter executed");
            }));
        };
    }

    public static class Config {
        // 配置属性
    }
}

在配置文件中使用自定义过滤器:

spring:
  cloud:
    gateway:
      routes:
      - id: my_route
        uri: http://httpbin.org:80
        predicates:
        - Path=/get
        filters:
        - name: MyCustomFilter

五、Gateway 限流

Spring Cloud Gateway中,有Filter过滤器,因此可以在“pre”类型的Filter中自行实现上述三种过滤器。但是限流作为网关最基本的功能,Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类,适用RedisLua脚本实现了令牌桶链接的方式。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类中,Lua脚本在如下图所示的文件夹中:

以案例的形式来讲解如何在SpringCloud Gateway中使用内置的限流过滤器工厂来实现限流。首先在工程的pom文件中引入Gateway的起步依赖和RedisReactive依赖,代码如下:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifatId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

在配置文件中做以下的配置:

server:
  port: 8081
spring:
  cloud:
    gateway:
      routes:
      - id: limit_route
        uri: lb://PRODUCTCENTOR   # PRODUCTCENTOR是注册到注册中心的服务名,格式为 lb://服务名
        predicates:
        - Path=/**
        filters:
        - StripPrefix=1
        - name: RequestRateLimiter  #拦截器,会对上述的请求进行拦击
          args:
            key-resolver: '#{@hostAddrKeyResolver}'
            redis-rate-limiter.replenishRate: 1
            redis-rate-limiter.burstCapacity: 3
  application:
    name: gateway-limiter
  redis:
    host: localhost
    port: 6379
    database: 0

过滤器StripPrefix,作用是去掉请求路径的最前面n个部分截取掉。StripPrefix=1就代表截取路径的个数为1,比如前端过来请求/test/good/1/view,匹配成功后,路由到后端的请求路径就会变成http://localhost:8888/good/1/view

在上面的配置文件,指定程序的端口为8081,配置了Redis的信息,并配置了RequestRateLimiter的限流过滤器,该过滤器需要配置三个参数:
【1】burstCapacity:令牌桶总容量。
【2】replenishRate:令牌桶每秒填充平均速率。
【3】key-resolver:用于限流的键的解析器的Bean对象的名字。它使用SpEL表达式根据#{@beanName}Spring容器中获取Bean对象。

KeyResolver需要实现resolve方法,比如根据Hostname进行限流,则需要用hostAddress去判断。实现完KeyResolver之后,需要将这个类的Bean注册到Ioc容器中。

public class HostAddrKeyResolver implements KeyResolver {

    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
    }

}

@Bean
public HostAddrKeyResolver hostAddrKeyResolver() {
    return new HostAddrKeyResolver();
}

可以根据URL去限流,这时KeyResolver代码如下:

public class UriKeyResolver implements KeyResolver {

    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getURI().getPath());
    }

}

@Bean
public UriKeyResolver uriKeyResolver() {
    return new UriKeyResolver();
}

也可以以用户的维度去限流:

// 省略部分代码
@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

jmeter进行压测,配置10 thread去循环请求lcoalhost:8081,循环间隔1s。从压测的结果上看到有部分请求通过,由部分请求失败。通过redis客户端去查看redis中存在的key。如下:

127.0.0.1:6379> keys *
1> "request_rate_limiter.<127.0.0.1>.timestamp"
2> "request_rate_limiter.<127.0.0.1>.tokens"

可见,RequestRateLimiter是使用Redis来进行限流的,并在redis中存储了2key。关注这两个key含义可以看lua源代码。

六、Zuul 与 Spring Cloud Gateway 比较

优点缺点
Gateway1、线程开销小2、使用轻量级 Netty 异步IO实现通信3、支持各种长连接,WebSocket4、Spring 官方推荐,重点支持,功能较 Zuul更丰富,支持限流监控等
Zuul1、编码模型简单2、开发调试运维简单

ZuulGateway压测结果: 休眠时间模仿后端请求时间,线程数2000,请求时间360秒=6分钟。配置情况:Gateway默认配置,Zuul网关的Tomcat最大线程数为400hystrix超时时间为100000

休眠时间测试样本,单位=个Zuul/Gateway平均响应时间,单位=毫秒Zuul/Gateway99%响应时间,单位=毫秒Zuul/Gateway错误次数,单位=个Zuul/Gateway错误比例Zuul/Gateway
休眠100ms294134/10593212026/5466136/1774104/00.04%/0%
休眠300ms101194/3999095595/148915056/16901114/01.10%/0%
休眠600ms51732/20126211768/297527217/32032476/04.79%/0%
休眠1000ms31896/12095619359/491446259/51153598/011.28%/0%

测试结果:Gateway在高并发和后端服务响应慢的场景下比Zuul的表现要好

七、SpringCloud GateWay 与 Nginx 组合使用

因为和GateWay相关所以这里介绍一下

NginxSpring Cloud Gateway可以组合使用,以实现高效的负载均衡和网关功能。Nginx通常用于处理静态内容、SSL终止、负载均衡等,而Spring Cloud Gateway主要用于动态路由、过滤和服务网关功能。下面是一个基本的配置示例,展示了如何将NginxSpring Cloud Gateway结合使用。这里主要说下Nginx中的配置:

配置Nginx作为反向代理,将外部请求转发到Spring Cloud Gateway

nginx.conf配置示例

http {
    upstream gateway {  # 定义一个名为 gateway 的上游服务器组,包含 Spring Cloud Gateway 的地址(localhost:8080)。
        server localhost:8080;
    }

    server { # 配置 Nginx 服务器块。
        listen 80;  # 监听80端口。

        location / { #  匹配所有请求。
            proxy_pass http://gateway; # http://gateway: 将请求转发到上游服务器组 gateway。
            proxy_set_header Host $host; # 设置一些头信息,用于保持客户端信息。
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
}

工作流程:
【1】客户端请求:客户端发送请求到Nginx
【2】Nginx转发:Nginx接收到请求后,将其转发到Spring Cloud Gateway
【3】Spring Cloud Gateway路由:Spring Cloud Gateway根据配置文件中的路由规则,将请求转发到对应的微服务。
【4】微服务响应:微服务处理请求并返回响应,通过Spring Cloud GatewayNginx返回给客户端。

SpringCloud GateWay 与 Nacos 组合使用

bootstrap.yml用于配置Nacos的基本信息:

spring:
  application:
    name: gateway-service #设置网关服务的名称。
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER_ADDR:localhost:8848} #Nacos 服务发现的地址。 ${NACOS_SERVER_ADDR}: 使用环境变量配置 Nacos 服务器地址,方便在不同环境中切换。
      config:
        server-addr: ${NACOS_SERVER_ADDR:localhost:8848} #Nacos 配置管理的地址。
        file-extension: yaml

可以将Spring Cloud Gateway的配置放在Nacos配置中心,这样可以实现配置的集中管理和动态更新。在Nacos中创建配置:
【1】登录Nacos控制台。
【2】创建一个新的配置,例如gateway-service.yaml
【3】在配置文件中添加路由规则,例如:

spring:
  cloud:
    gateway:
      routes:
        - id: example-service
          uri: lb://example-service
          predicates:
            - Path=/example/**
        - id: another-service
          uri: lb://another-service
          predicates:
            - Path=/another/**

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

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

相关文章

前端方案:根据链接生成二维码

前言&#xff1a; 虽然在很多时候&#xff0c;生成二维码的操作都是由后端进行操作。但是在某些特定的场景里&#xff0c;难免会需要前端来完成链接生成二维码的操作&#xff0c;在这里我们提供一个插件来完成&#xff0c;这个插件就是qrcode。 官方地址 安装&#xff1a; …

Enemy Golem 卡通石头人怪物模型带骨骼动画动作

包含9个动画。 信息: -模型有9.450个涵洞。 -矿脉x 4 -纹理:彩色、普通、蒙版、AO、发射型(2048x2048尺寸) 下载:​​Unity资源商店链接资源下载链接 效果图:

【多模态论文阅读系列二】— MiniCPM-V

校招/实习简历修改、模拟面试欢迎私信《MiniCPM-V: A GPT-4V Level MLLM on Your Phone》 在本节中&#xff0c;我们介绍了MiniCPM-V的模型架构&#xff0c;概述了其总体结构和自适应高分辨率视觉编码方法。MiniCPM-V系列的设计理念是在性能和效率之间实现良好的平衡&#xff0…

默语是谁?

默语是谁&#xff1f; 大家好&#xff0c;我是 默语&#xff0c;别名默语博主&#xff0c;擅长的技术领域包括Java、运维和人工智能。我的技术背景扎实&#xff0c;涵盖了从后端开发到前端框架的各个方面&#xff0c;特别是在Java 性能优化、多线程编程、算法优化等领域有深厚…

一文了解 Linux 系统的文件权限管理

文章目录 引入Linux文件权限模型查看文件权限权限信息解析修改文件权限符号模式八进制数字模式 引入 在Linux操作系统中&#xff0c;我们想查看我们对文件拥有哪些权限时&#xff0c;可以在终端键入ls -l或ll命令&#xff0c;终端会输出当前路径下的文件信息&#xff0c;如文件…

vue3集成electron

安装说明 vue集成electron时&#xff0c;会用到两个依赖。分别是electron和electron-builder&#xff0c;前者是开发环境下使用&#xff0c;后者是打包部署时使用。安装时&#xff0c;可在线安装也可离线安装。所谓离线安装就是自己下载好用到的包&#xff0c;然后放到指定目录…

Spring Boot知识管理系统:安全与合规性

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

HI3516DV500 相机部分架构初探

Hi3516DV500 是一颗面向视觉行业推出的高清智能 Soc。该芯片最高支持 2 路 sensor 输入&#xff0c;支持最高 5M30fps 的 ISP 图像处理能力&#xff0c;支持 2F WDR、多级降噪、六轴防 抖、多光谱融合等多种传统图像增强和处理算法&#xff0c;支持通过 AI 算法对输入图像进行实…

Mysql(3)—数据库相关概念及工作原理

一、数据库相关概念 ​ 数据库&#xff08;Database, DB&#xff09; &#xff1a; 数据库是一个以某种有组织的方式存储的数据集合。它通常包括一个或多个不同的主题领域或用途的数据表。 数据库管理系统&#xff08;Database Management System, DBMS&#xff09; &#xf…

树莓派应用--AI项目实战篇来啦-15.SSD Mobilenet V3目标检测

1. Mobilenet 介绍 Mobilenet 是一种专为移动和嵌入式视觉应用而设计的卷积神经网络。它们不使用标准的卷积层&#xff0c;而是基于使用深度可分离卷积的简化架构&#xff0c;使用这种架构&#xff0c;我们可以为移动和嵌入式设备&#xff08;例如&#xff1a;树莓派&#xff0…

Navicat 关于SQLserver的连接问题

1、如果出以下问题&#xff0c;就需要安装驱动程序&#xff0c;如下图&#xff1a; 2、在Navicat的根目录下有一个驱动安装文件&#xff0c;安装后就可以连接上了.

Cisco ACI常见问题FAQ科普

这里有个思科的官方链接&#xff0c;不过里面很多是商务说辞&#xff0c;也就是吹牛&#xff0c;仅做为参考。 https://www.cisco.com/c/dam/global/en_sg/solutions/data-center-virtualization/application-centric-infrastructure/insieme_faq.pdf 下面是我自己的理解 0 …

Windows 安装Redis(图文详解)

Windows 安装Redis&#xff08;图文详解&#xff09; Redis是什么数据库&#xff1f; Remote Dictionary Server(Redis) 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库&#xff0c;并提供多种语…

CleanMyMac X4.15.9破解版激活码许可证

CleanMyMac X&#xff1a;你的Mac电脑的“私人健身教练” ### 一键瘦身&#xff0c;轻松给Mac电脑“减减肥” &#x1f3cb;️‍♂️ 大家有没有觉得&#xff0c;自己的Mac电脑用久了&#xff0c;就变得越来越“胖”&#xff0c;越来越慢呢&#xff1f;别怕&#xff0c;今天我要…

Qt获取磁盘信息+表格显示

效果展示 主要代码 获取磁盘相关数据 获取磁盘数据 Qt 没有提供相关的接口&#xff0c;需要使用 Windows API。接口解释如下&#xff1a; BOOL GetDiskFreeSpaceExW([in, optional] LPCWSTR lpDirectoryName,[out, optional] PULARGE_INTEGER lpFreeBytesAvailable…

chattts一步步的记录,先跑起来。

0.下载git工具 Git - Downloads (git-scm.com)https://git-scm.com/downloads Download – TortoiseGit – Windows Shell Interface to Githttps://tortoisegit.org/download/ 1.安装 随意&#xff0c;可以安汉化&#xff0c;也可不安。无所谓 2.建个目录&#xff0c;我的上…

Prometheus+Grafana 监控 K8S Ingress-Ningx Controller

文章目录 一、prometheus中添加ingress-nginx的服务发现配置二、ingress-nginx controller的service添加端口暴露监控指标三、grafana添加ingress-nginx controller的监控模版 ingress-nginx默认是没有开启监控指标的&#xff0c;需要我们在ingress-nginx controller的svc里面开…

K8S配置MySQL主从自动水平扩展

前提环境 操作系统Ubuntu 22.04 K8S 1.28.2集群&#xff08;1个master2个node&#xff09; MySQL 5.7.44部署在K8S的主从集群 metrics-server v0.6.4 概念简介 在K8s中扩缩容分为两种 ●Node层面&#xff1a;对K8s物理节点扩容和缩容&#xff0c;根据业务规模实现物理节点自动扩…

数字媒体技术基础:色度子采样(4:4:4、4:2:2 、4:2:0)

在数字视频处理中&#xff0c;色度子采样 Chroma Subsampling可以用于压缩视频文件的大小&#xff0c;同时在大多数情况下保持较高的视觉质量&#xff0c;它的原理基于人类视觉系统对亮度 Luminance比对色度 Chrominance更加敏感这一特点。 一、 采样格式的表示方法 色度子采样…

一个技巧实现在SharePoint中使用Copilot

前几天写了在onedrive中使用copilot对单个文件进行提问汇总分析与对多个文件进行比较汇总提问等&#xff1a; Copilot重磅更新&#xff01;OneDrive全新功能炸裂 很多小伙伴表示特别受用。 于是他们在纷纷尝试了一段时间后&#xff0c;开始把目光转向SharePoint和teams文件&a…