Spring Cloud Gateway 使用 Redis 限流使用教程
从本文开始,笔者将总结 spring cloud 相关内容的教程
版本选择
为了适应 java8,笔者选择了下面的版本,后续会出 java17的以SpringBoot3.0.X为主的教程
SpringBoot 版本 2.6.5
SpringCloud 版本 2021.0.1
SpringCloudAlibaba 版本 2021.0.1.0
SpringCloudAlibaba github 版本说明截图

SpringCloud 官网:https://spring.io/projects/spring-cloud
Spring Cloud Alibaba 官网:https://sca.aliyun.com/zh-cn/
目录
1、环境准备
2、项目创建
3、测试限流
4、改进限流返回
5、项目代码
1、环境准备
本文讲解Spring Cloud Gateway 使用 Redis 限流,注册中心使用 Nacos
Macos 官网:https://nacos.io/zh-cn/index.html
Nacos 安装这里不做过多介绍,不了解的朋友可以参考
Nacos 单机安装:https://blog.csdn.net/wsjzzcbq/article/details/123916233
Nacos 集群安装:https://blog.csdn.net/wsjzzcbq/article/details/123956116
笔者使用 docker 开启 nacos 和 redis
Spring Cloud Alibaba 2021.0.1.0 版本对应的nacos版本是 1.4.2
笔者使用的 Naocs 版本是 2.0.0-bugfix,redis 版本是 7.0.6

2、项目创建
新建 maven 聚合项目 cloud-learn
最外层父工程 cloud-learn 的 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.wsjzzcbq</groupId><artifactId>cloud-learn</artifactId><version>1.0-SNAPSHOT</version><modules><module>gateway-learn</module><module>consumer-learn</module></modules><packaging>pom</packaging><repositories><repository><id>naxus-aliyun</id><name>naxus-aliyun</name><url>https://maven.aliyun.com/repository/public</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots></repository></repositories><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.5</version><relativePath/></parent><properties><spring-cloud.version>2021.0.1</spring-cloud.version><spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version><alibaba-nacos-discovery.veriosn>2021.1</alibaba-nacos-discovery.veriosn><alibaba-nacos-config.version>2021.1</alibaba-nacos-config.version><spring-cloud-starter-bootstrap.version>3.1.1</spring-cloud-starter-bootstrap.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${alibaba-nacos-discovery.veriosn}</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${alibaba-nacos-config.version}</version></dependency><!--spring-cloud-dependencies 2020.0.0 版本不在默认加载bootstrap文件,如果需要加载bootstrap文件需要手动添加依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>${spring-cloud-starter-bootstrap.version}</version></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.40</version></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>
然后创建2个子工程 consumer-learn 和 gateway-learn
gateway-learn 中配置路由转发到 consumer-learn
consumer-learn 工程 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>cloud-learn</artifactId><groupId>com.wsjzzcbq</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>consumer-learn</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--feign负载均衡--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
consumer-learn 工程 启动类
package com.wsjzzcbq;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** ConsumerApplication** @author wsjz* @date 2023/09/17*/
@EnableFeignClients
@SpringBootApplication
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}
}
consumer-learn 工程 配置文件
spring.application.name=consumer-learn
server.port=8081
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
spring.cloud.nacos.discovery.server-addr=192.168.31.152:8848
spring.cloud.nacos.discovery.namespace=public
logging.level.com.alibaba.cloudlearnconsumer.feign.ProducerService=DEBUG
consumer-learn 工程 controller
package com.wsjzzcbq.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** ConsumerController** @author wsjz* @date 2023/09/17*/
@RestController
public class ConsumerController {@RequestMapping("/name")public String user() {return "宝剑锋从磨砺出,梅花香自苦寒来";}
}
gateway-learn
gateway-learn 工程 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>cloud-learn</artifactId><groupId>com.wsjzzcbq</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>gateway-learn</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- gateway负载均衡需要下面依赖,不添加会报错503--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><!--redis使用较高版本,5以上版本,不要使用windows版redis,低版本redis不支持lua中的命令--><!--https://blog.csdn.net/wxxiangge/article/details/95024214/--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId></dependency><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
gateway-learn 工程 启动类
package com.wsjzzcbq;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** GatewayApplication** @author wsjz* @date 2023/09/17*/
@SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}
限流需要实现 KeyResolver 接口的 resolve 方法
在 resolve 方法中返回限流的维度,如请求路径、ip地址、请求参数等
笔者这里限流维度是请求路径
package com.wsjzzcbq.limit;import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** ApiKeyResolver** @author wsjz* @date 2023/09/17*/
@Component
public class ApiKeyResolver implements KeyResolver {@Overridepublic Mono<String> resolve(ServerWebExchange exchange) {System.out.println("API限流: " + exchange.getRequest().getPath().value());return Mono.just(exchange.getRequest().getPath().value());}
}
gateway-learn 工程 配置文件
server:port: 9000
spring:application:name: gateway-learnredis:host: 192.168.31.152password: 123456timeout: 5000database: 0cloud:nacos:discovery:server-addr: http://192.168.31.152:8848gateway:routes:- id: consumer-learnuri: lb://consumer-learnpredicates:- Path=/cloudlearn/consumer/**filters:- name: RequestRateLimiterargs:key-resolver: "#{@apiKeyResolver}"redis-rate-limiter.replenishRate: 1 #生成令牌速率:个/秒redis-rate-limiter.burstCapacity: 2 #令牌桶容量redis-rate-limiter.requestedTokens: 1 #每次消费的Token数量,默认是 1- StripPrefix=2
配置说明:
RequestRateLimiter 是 gateway 提供的限流过滤器
#{@apiKeyResolver} 是笔者实现的 ApiKeyResolver
redis-rate-limiter.replenishRate 生成令牌的速率每秒几个
redis-rate-limiter.burstCapacity 令牌桶容量
redis-rate-limiter.requestedTokens 每次消费的令牌数量
当请求到网关以 /cloudlearn/consumer/ 为开头前缀时,会路由到 consumer-learn 服务上
创建完成的项目结构

3、测试限流
分别启动 consumer-learn 和 gateway-learn
登录 Nacos 控制台查看

启动成功后,可在Naocs 控制台查看注册服务信息
浏览器访问测试限流:http://localhost:9000/cloudlearn/consumer/name
运行效果

可以看到当1秒钟内请求超过2次时会被限流
4、改进限流返回
上面代码实现了限流,但限流触发后返回的是429,不利于前端处理,这里我们可以在默认的限流过滤器基础上进行改进,自定义限流时的返回
新建 NewRequestRateLimiterGatewayFilterFactory 类
继承默认的 RequestRateLimiterGatewayFilterFactory
package com.wsjzzcbq.filter;import com.alibaba.fastjson2.JSONObject;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.HttpStatusHolder;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;/*** NewRequestRateLimiterGatewayFilterFactory** @author wsjz* @date 2023/09/17*/
@Component
public class NewRequestRateLimiterGatewayFilterFactory extends RequestRateLimiterGatewayFilterFactory {private final RateLimiter defaultRateLimiter;private final KeyResolver defaultKeyResolver;private boolean denyEmptyKey = true;private String emptyKeyStatusCode = HttpStatus.FORBIDDEN.name();public NewRequestRateLimiterGatewayFilterFactory(RateLimiter defaultRateLimiter, KeyResolver defaultKeyResolver) {super(defaultRateLimiter, defaultKeyResolver);this.defaultRateLimiter = defaultRateLimiter;this.defaultKeyResolver = defaultKeyResolver;}@Overridepublic GatewayFilter apply(Config config) {System.out.println("过滤限流");KeyResolver resolver = (KeyResolver)this.getOrDefault(config.getKeyResolver(), this.defaultKeyResolver);RateLimiter<Object> limiter = (RateLimiter)this.getOrDefault(config.getRateLimiter(), this.defaultRateLimiter);boolean denyEmpty = (Boolean)this.getOrDefault(config.getDenyEmptyKey(), this.denyEmptyKey);HttpStatusHolder emptyKeyStatus = HttpStatusHolder.parse((String)this.getOrDefault(config.getEmptyKeyStatus(), this.emptyKeyStatusCode));return (exchange, chain) -> {return resolver.resolve(exchange).defaultIfEmpty("____EMPTY_KEY__").flatMap((key) -> {if ("____EMPTY_KEY__".equals(key)) {if (denyEmpty) {ServerWebExchangeUtils.setResponseStatus(exchange, emptyKeyStatus);return exchange.getResponse().setComplete();} else {return chain.filter(exchange);}} else {String routeId = config.getRouteId();if (routeId == null) {Route route = (Route)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);routeId = route.getId();}return limiter.isAllowed(routeId, key).flatMap((response) -> {Iterator var4 = response.getHeaders().entrySet().iterator();while(var4.hasNext()) {Map.Entry<String, String> header = (Map.Entry)var4.next();exchange.getResponse().getHeaders().add((String)header.getKey(), (String)header.getValue());}if (response.isAllowed()) {return chain.filter(exchange);} else {ServerHttpResponse httpResponse = exchange.getResponse();httpResponse.getHeaders().set("Content-Type", "application/json");JSONObject json = new JSONObject();json.put("code", 0);json.put("msg", "当前请求人数较多,请稍后再访问");DataBuffer dataBuffer = httpResponse.bufferFactory().wrap(json.toJSONString().getBytes(StandardCharsets.UTF_8));return httpResponse.writeWith(Mono.just(dataBuffer));}});}});};}private <T> T getOrDefault(T configValue, T defaultValue) {return configValue != null ? configValue : defaultValue;}
}
修改配置文件
配置我们自定义的限流过滤器
server:port: 9000
spring:application:name: gateway-learnredis:host: 192.168.31.152password: 123456timeout: 5000database: 0cloud:nacos:discovery:server-addr: http://192.168.31.152:8848gateway:routes:- id: consumer-learnuri: lb://consumer-learnpredicates:- Path=/cloudlearn/consumer/**filters:- name: NewRequestRateLimiterargs:key-resolver: "#{@apiKeyResolver}"redis-rate-limiter.replenishRate: 1 #生成令牌速率:个/秒redis-rate-limiter.burstCapacity: 2 #令牌桶容量redis-rate-limiter.requestedTokens: 1 #每次消费的Token数量- StripPrefix=2
重新启动 gateway-learn
请求测试

5、项目代码
码云地址:https://gitee.com/wsjzzcbq/csdn-blog/tree/master/cloud-learn
至此完
相关文章:
Spring Cloud Gateway 使用 Redis 限流使用教程
从本文开始,笔者将总结 spring cloud 相关内容的教程 版本选择 为了适应 java8,笔者选择了下面的版本,后续会出 java17的以SpringBoot3.0.X为主的教程 SpringBoot 版本 2.6.5 SpringCloud 版本 2021.0.1 SpringCloudAlibaba 版本 2021.0.1.…...
Qt事件系统 day7
Qt事件系统 day7 事件系统 在Qt中,事件是派生自抽象QEvent类的对象,它表示应用程序内发生的事情或应用程序需要知道的外部活动的结果。事件可以由QObject子类的任何实例接收和处理,但它们与小部件尤其相关。Qt程序需要在main()函数创建一个…...
微服务拆分的思考
一、前言 前面几篇文章介绍了微服务核心的两个组件:注册中心和网关,今天我们来思考一下微服务如何拆分,微服务拆分难度在于粒度和层次,粒度太大拆分的意义不大,粒度太小开发、调试、运维会有很多坑。 二、微服务划分…...
DateUtil工具类记录
为支持日常工作需要,记录所用到的一些关于时间的工具类方法。随时进行补充。 /*** Description:获取两个日期之间的天数差* Author:hanyq* Date:2023/9/19 11:23*/public static int getDateDifference(Date startDate,Date endDate){int days 0;try {Calendar st…...
可信执行环境简介:ARM 的 TrustZone
目录 可信执行环境安全世界与普通世界 - 上下文切换机制ARMv7 中的异常处理ARMv8 中的异常处理 信任区商业实施TrustZone 本身的漏洞高通Trustonic 信任区强化的弱点结论声明 可信执行环境 具有信任区的 ARM 处理器实现了架构安全性每个物理处理器内核提供两个虚拟的扩展 核心…...
【音视频流媒体】 3、ffmpeg、ffplay、ffprobe 超详细介绍
文章目录 一、ffmpeg1.1 安装1.2 基本参数 二、ffprobe2.1 查编码格式2.2 查视频时长 五、视频转流5.1 MP4转H2645.2 H264转MP45.3 AVI转MP45.4 MP4转H265 六、视频文件6.1 播放6.2 filter 过滤器6.2.1 crop 6.3 视频截取6.4 视频拼接6.5 获取分辨率 七、视频和图7.1 视频抽帧7…...
解决kong部署自定义插件报 helloworld plugin is enabled but not installed
背景 我使用的是docker环境部署,使用的是自定义挂载plugins路径 -e "KONG_LUA_PACKAGE_PATH/plugins/?.lua" \ -v "/plugins:/plugins" \ -e "KONG_PLUGINSbundled,helloworld" \但是当我只需docker run的时候就报错 [error] 1#0:…...
动态数据源自定义SqlSessionFactoryBean时mybatis plus配置失效
环境: 动态数据源spring-boot 2.7.15mybatis-plus 3.5.2 yaml配置: spring:datasource:db100:username: xxxpassword: xxxjdbc-url: jdbc:kingbase8://xxx.xxx.xxx.xxx:54321/100driver-class-name: com.kingbase8.Driver# url: jdbc:postgresql://xxx…...
【Qt控件之QDialogButtonBox】概述及使用
概述 QDialogButtonBox类是一个小部件,它以适合当前小部件样式的布局呈现按钮。 对话框和消息框通常以符合该台界面指南的布局呈现按钮。不同的平台会有不同的对话框布局。QDialogButtonBox允许发人员向其添加按钮,并将自使用用户的桌面环境所适合的布局…...
IPv6知识概述 - ND协议
IPv6知识概述 - ND协议 参考文章:https://blog.csdn.net/Gina_wj/article/details/106708770 IPv6基础篇(四):邻居发现协议NDP ND协议功能概述 ND(Neighbor Discovery,邻居发现)协议是IPv6的…...
react-redux的connect函数实现
react-redux对store订阅的实现原理: storeContext.js import { createContext } from "react";export const StoreContext createContext() connect.js import React, { PureComponent } from react // import store from ../../store; import {Stor…...
Vue3使用Vite创建项目
node版本:node -v v18.16.0 npm版本: npm -v 9.5.1 Vite Vite:是一种新型前端构建工具,能够显著提升前端开发体验 脚手架,创建Vue项目,替代 Vue-cli 基于Vite创建vue项目: 1.npm create vitelatest 2.完…...
NCV7724DQBR2G车规级半桥电机驱动芯片-专为汽车,工业自动化应用提供完美解决方案
车规级半桥电机驱动芯片是一种用于驱动直流电机的芯片,常用于电动汽车、电动自行车等领域。它可以控制电机的转速和方向,并且具有过流保护、过温保护等功能,可以保证电机的安全运行。 NCV7724DQBR2G是一款车规级八通道半桥驱动器,…...
NSS [GWCTF 2019]枯燥的抽奖
NSS [GWCTF 2019]枯燥的抽奖 开题让我猜字符串,这种题目肯定不是猜,应该是类似于php伪随机数。 dirsearch扫他一下。 访问/check.php得到源码。 分析一下代码。 通过PHP伪随机数从字符库$str_long1中选取20个字符组成字符串,返回给我们前十…...
微信小程序会议OA系统
Flex弹性布局 Flex弹性布局是一种 CSS3 的布局模式,也叫Flexbox。它可以让容器中的元素按一定比例自动分配空间,使得它们在不同宽度、高度等情况下仍能保持整齐和密集不间隙地排列。 在使用Flexbox弹性布局时,首先需要创建一个容器和若干个…...
CICD:Circle CI 实现CICD
持续集成解决什么问题 提高软件质量效率迭代便捷部署快速交付、便于管理 持续集成(CI) 集成,就是一些孤立的事物或元素通过某种方式集中在一起,产生联系,从而构建一个有机整体的过程。 持续,就是指长期…...
竞赛 深度学习YOLO安检管制物品识别与检测 - python opencv
文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov55 模型训练6 实现效果7 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 **基于深度学习YOLO安检管制误判识别与检测 ** 该项目较为新颖,适合作为竞赛课题方向&…...
【华为OD机试python】斗地主之顺子【2023 B卷|100分】
【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 在斗地主扑克牌游戏中, 扑克牌由小到大的顺序为:3,4,5,6,7,8,9,10,J,Q,K,A,2, 玩家可以出的扑克牌阵型有:单张、对子、顺子、飞机、炸弹等。 其中顺子的出牌规则为:由至少5张由小到大…...
ant design DatePicker禁用之前的时间
1、代码 <DatePicker fieldProps{disabledDate: (current: any) > {return current < moment().startOf(day);}}/>2、效果...
C语言---预处理详解
1.预定义符号 在C语言中有一些内置的预定义符号 __FILE__ __LINE__ __DATE__ __TIME__ __STDC__//进行编译的源文件 //文件当前的行号 //文件被编译的日期 //文件被编译的时间 //如果编译器遵循ANSI C,其值为1,否则未定义 编译器在__STDC__报错,说明,v…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
