分布式系列之限流组件

概述

在高并发场景下,请求量瞬间到达,后端服务器即使有缓存、集群主备、分库分表、容错降级等措施,也有可能扛不住这请求量,因此可考虑引入限流组件。限流的目的:防止恶意请求流量或流量超出系统承载。

应用场景:

  • 网关层校验流量,拦截非法请求,或直接抛弃部分流量(后来的流量,如秒杀系统)
  • 实时场景下的数据迁移或复制(如Kafka分区重分配)

本文从限流算法、限流环节、限流框架几个层次加以讲述。

限流算法

主要有两大类:窗口算法(也有叫做计数器算法的,思想其实很类似,包括固定窗口算法和滑动窗口算法)、桶算法(包括漏桶算法、令牌桶算法)。

计数器算法

该算法会维护一个counter,规定在单位时间内counter的大小不能超过最大值,每隔固定时间就将counter的值置零。如果这个counter大于设定的阈值,那么系统就开始拒绝请求以保护系统的负载。

固定窗口

固定窗口就是指定的单位时间,比如一分钟,限制次数为Max,则最大值为Max,超过Max的请求被抛弃。存在临界问题:单位时间的左区间可能有大量请求,直接超过Max。

/*** 指定过期时间自增计数器,默认每次+1,非滑动窗口** @param key 计数器自增key* @param expireTime 过期时间* @param unit  时间单位*/
public long incrCount(String key, int expireTime, TimeUnit unit);/*** 指定过期时间自增计数器,单位时间内超过最大值rateThreshold返回true,否则返回false** @param key 限流key* @param rateThreshold 限流阈值* @param expireTime 固定窗口时间* @param unit 时间单位*/
public boolean rateLimit(final String key, final int rateThreshold, int expireTime, TimeUnit unit);

滑动窗口

固定窗口可看成是滑动窗口的特例。滑动窗口将固定窗口再等分为多个小的窗口,每一次对一个小的窗口进行流量控制。可解决固定窗口的临界问题。

漏桶算法

Leaky Bucket,水(请求)先进入到漏桶(预先维护的容量固定)里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,漏桶算法能强行限制数据的传输速率。
在这里插入图片描述
核心:请求来以后,直接进桶,然后桶根据自己的漏洞大小慢慢往外面漏。使用一个FIFO的队列,一端负责不断的放入请求,另外一端负责吐出请求。

好处:可将系统的处理能力维持在一个比较平稳的水平
缺点:不能应对实际场景,比如突然暴增的流量。

令牌桶算法

Token Bucket Algorithm,用于限制速率。

令牌桶会以一个恒定的速率(预定义)向固定容量(要限制流量的大小)大小桶中放入令牌,当有流量来时则取走一个或多个令牌。当桶中没有令牌则将当前请求丢弃或阻塞等待,直到有足够的令牌为止。可实现平滑突发限流,允许一定的突发请求,但总体速率会保持在设定的限制内。
在这里插入图片描述
参考实现:Guava RateLimiter

漏桶算法和令牌桶算法对比

令牌桶算法和漏桶算法的不同之处在于处理瞬间到达的大流量的不同:

  • 令牌桶算法由于在令牌桶里攒很多令牌,因此在大流量到达一瞬间可以一次性将队列中所有的请求都处理完,然后按照恒定的速度处理请求;
  • 漏桶算法则一直有一个恒等的阈值,在大流量到达时,也会将多余的请求拒绝。

限流环节

限流从环节(也有叫粒度)来分析,有:网关限流,服务限流,接口限流。

网关限流

网关,即接入层,是请求流量的入口,一般可考虑使用Nginx限流。

Nginx自带两个模块:

  • 连接数限流模块:ngx_http_limit_conn_module(简称limit_conn,如果读者们在某些书籍或Blog里看到这个简称,就表示这个模块)
  • 请求限流模块:基于漏桶算法实现,ngx_http_limit_req_module(简称limit_req,同上)。

此外,可以使用OpenResty提供的lua限流模块lua-resty-limit-traffic,以及tengine增强版httplimitreqcn。

limit_conn

limit_conn模块用于限制连接数量,特别是来自单个IP地址的连接数量。并非所有的连接都被计数。只有当服务器处理完请求且已经读取整个请求头时,连接才被计数。

官网的示例配置:

http {limit_conn_zone $binary_remote_addr zone=addr:10m;server {location /download/ {limit_conn addr 1;}	}
}

配置解读:
limit_conn_zone $binary_remote_addr zone=addr:10m;:为共享内存区域设置参数,该区域将保留各种Key键的状态。状态包含当前的连接数。Key可以包含文本,变量,他们的组合。只能用于http语法块。

$binary_remote_addr:对于IPv4地址,变量的大小始终为4个字节,对于IPv6地址则为16个字节。存储状态在32位平台上始终占用32或64个字节,在64位平台上占用64个字节。一个兆字节的区域可保存大约32000个32字节的状态或大约16000个64字节的状态。如果区域存储耗尽,服务器会将错误返回给所有其他请求。10M可存储160000个状态。

limit_conn addr 1:设置给定键值的共享内存区域和最大允许连接数。超过此限制时,服务器将返回503错误以回复请求。用于http,server,location这些语法块内。

limit_req

用于限制每一个请求的处理速率,即每个IP地址的请求的处理速率。

官网的示例配置:

http {limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;server {location /search/ {limit_req zone=one burst=5;}
}

配置解读:
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;:区域名称为one,大小为10m,平均处理的请求频率不能超过每秒一次。键值是客户端IP,$binary_remote_addr变量,可以将每条状态记录的大小减少到64个字节,这样1M的内存可以保存大约1万6千个64字节的记录。如果限制域的存储空间耗尽,对于后续所有请求,服务器都会返回503错误。

limit_req zone=one burst=5;:平均每秒不超过1个请求,并且突发不超过5个请求。超过处理能力范围的,直接drop,表现为对收到的请求无延时。

服务限流

应用级别,对应用里涉及到的所有的接口类和方法都增加限流机制。

接口限流

接口层次的限流,粒度最小,用于某个Controller类或方法,

限流框架

Guava RateLimiter

Guava提供的抽象类RateLimiter源码很长,略。用于限制方法的调用频率,它基于令牌桶算法

其实现类有两个,对应两种限流模式:

  1. SmoothBursty:稳定模式,令牌生成速度恒定,平滑突发限流;
  2. SmoothWarmingUp:渐进模式,令牌生成速度缓慢提升直到维持在一个稳定值,平滑预热限流

两种模式实现思路类似,主要区别在等待时间的计算上。

局限性:

  1. 仅适用于单体应用
  2. 不保证公平性访问

Spring Cloud GateWay

需要引入依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--基于 reactive stream 的redis -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

引入spring-cloud-starter-gateway后,则引入子依赖spring-cloud-gateway-server,后者源码里带有request_rate_limiter.lua脚本:
在这里插入图片描述
配置:

spring:cloud:gateway:routes:- id: requestratelimiter_routeuri: lb://gateway-demoorder: 10000predicates:- Path = /admin/**filters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 1 # 流速每秒1个redis-rate-limiter.burstCapacity: 3 # 令牌桶容积key - resolver: "#{@remoteAddrKeyResolver}" # SPEL表达式去的对应的bean- StripPrefix = 1

配置Bean方法,多维度限流量的入口:

@Bean
KeyResolver remoteAddrKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}

GateWay提供RateLimiter接口,AbstractRateLimiter抽象类,以及实现类RedisRateLimiter,接口主要有一个方法Mono<Response> isAllowed(String routeId, String id);,RedisRateLimter核心源码:

public Mono<Response> isAllowed(String routeId, String id) {Config routeConfig = getConfig().getOrDefault(routeId, defaultConfig);int replenishRate = routeConfig.getReplenishRate();int burstCapacity = routeConfig.getBurstCapacity();try {List<String> keys = getKeys(id);/* returns unixtime in seconds.*/List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "", Instant.now().getEpochSecond() + "", "1");// 核心,执行redis LUA脚本Flux<List<Long>> flux = this.redisTemplate.execute(this.script, keys, scriptArgs);return flux.onErrorResume(throwable -> Flux.just(Arrays.asList(1L, -1L))).reduce(new ArrayList<Long>(), (longs, l) -> {longs.addAll(l);return longs;}).map(results -> {boolean allowed = results.get(0) == 1L;Long tokensLeft = results.get(1);Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft));if (log.isDebugEnabled()) {log.debug("response: " + response);}return response;});} catch (Exception e) {log.error("Error determining if user allowed from redis", e);}return Mono.just(new Response(true, getHeaders(routeConfig, -1L)));
}

Sentinel

另起一篇,参考服务容错框架Sentinel入门。

Bucket4j

Bucket4j是一个基于令牌桶算法实现的强大的限流库,支持单机限流,还支持通过诸如Hazelcast、Ignite、Coherence、Infinispan或其他兼容 JCache API(JSR 107)规范的分布式缓存实现分布式限流。

3个核心概念:Bucket、Bandwidth、Refill。

Bucket:接口,代表令牌桶的具体实现,操作的入口。提供诸如tryConsumetryConsumeAndReturnRemaining方法用于消费令牌。可通过下面的构造方法来创建Bucket:

Bucket bucket = Bucket4j.builder().addLimit(limit).build();
if (bucket.tryConsume(1)) {log.info("ok");
} else {log.info("error");
}

Bandwidth:带宽,可理解为限流规则。Bucket4j提供两种方法来创建Bandwidth:

  • simple:桶大小和填充速度是一样的,表示桶大小为10,填充速度为每分钟10个令牌:
Bandwidth limit = Bandwidth.simple(10, Duration.ofMinutes(1));
  • classic:更灵活,可自定义填充速度:
// 贪婪策略:桶大小为10,填充速度为每分钟5个令牌;
Refill filler = Refill.greedy(5, Duration.ofMinutes(1));
Bandwidth limit = Bandwidth.classic(10, filler);

Refill:用于填充令牌桶,可以通过它定义填充速度,Bucket4j有两种填充令牌的策略:

  • intervally:间隔策略。间隔策略创建Refill:Refill filler = Refill.intervally(5, Duration.ofMinutes(1));// 每隔一分钟,填充 5 个令牌
    所谓间隔策略指的是每隔一段时间,一次性的填充所有令牌。
  • greedy:贪婪策略,参考上面的简单例子

Resilience4j

Resilience4j是一款轻量级、易使用的高可用框架,设计灵感就来自于Netflix Hystrix。自从Hystrix停止维护之后,官方也推荐使用Resilience4j来代替Hystrix。

Resilience4j的底层采用Vavr(一个非常轻量级的Java函数式库),以装饰器模式提供对函数式接口或lambda表达式的封装,提供高可用机制:重试(Retry)、熔断(Circuit Breaker)、限流(RateLimiter)、限时(Timer Limiter)、隔离(Bulkhead)、缓存(Cache)和降级(Fallback)。

其中,RateLimiter是请求频率限流,Bulkhead是并发量限流。

Resilience4j提供两种限流的实现:SemaphoreBasedRateLimiter和AtomicRateLimiter。SemaphoreBasedRateLimiter基于信号量实现,用户的每次请求都会申请一个信号量,并记录申请的时间,申请通过则允许请求,申请失败则限流,另外有一个内部线程会定期扫描过期的信号量并释放,很显然这是令牌桶的算法。AtomicRateLimiter和上面的经典实现类似,不需要额外的线程,在处理每次请求时,根据距离上次请求的时间和生成令牌的速度自动填充。

Resilience4j也提供两种隔离的实现:SemaphoreBulkhead和ThreadPoolBulkhead,通过信号量或线程池控制请求的并发数。

同时使用限流和隔离的例子:

// 创建一个Bulkhead,最大并发量为150
BulkheadConfig bulkheadConfig = BulkheadConfig.custom().maxConcurrentCalls(150).maxWaitTime(100).build();
Bulkhead bulkhead = Bulkhead.of("backendName", bulkheadConfig);// 创建RateLimiter,每秒允许一次请求
RateLimiterConfig rateLimiterConfig = RateLimiterConfig.custom().timeoutDuration(Duration.ofMillis(100)).limitRefreshPeriod(Duration.ofSeconds(1)).limitForPeriod(1).build();
RateLimiter rateLimiter = RateLimiter.of("backendName", rateLimiterConfig);// 使用Bulkhead和RateLimiter装饰业务逻辑
Supplier<String> supplier = () -> backendService.doSomething();
Supplier<String> decoratedSupplier = Decorators.ofSupplier(supplier).withBulkhead(bulkhead).withRateLimiter(rateLimiter).decorate();// 调用业务逻辑
Try<String> try = Try.ofSupplier(decoratedSupplier);
assertThat(try.isSuccess()).isTrue();

Resilience4j在功能特性上比Bucket4j强大不少,而且还支持并发量限流,但不支持分布式限流。

拓展

TimeLimiter和RateLimiter

除了RateLimiter,在Guava包里还有个TimeLimiter接口:

@DoNotMock("Use FakeTimeLimiter")
@ElementTypesAreNonnullByDefault
@J2ktIncompatible
@GwtIncompatible
public interface TimeLimiter {<T> T newProxy(T target, Class<T> interfaceType, long timeoutDuration, TimeUnit timeoutUnit);default <T> T newProxy(T target, Class<T> interfaceType, Duration timeout) {return this.newProxy(target, interfaceType, Internal.toNanosSaturated(timeout), TimeUnit.NANOSECONDS);}@ParametricNullness@CanIgnoreReturnValue<T> T callWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException, InterruptedException, ExecutionException;@ParametricNullness@CanIgnoreReturnValuedefault <T> T callWithTimeout(Callable<T> callable, Duration timeout) throws TimeoutException, InterruptedException, ExecutionException {return this.callWithTimeout(callable, Internal.toNanosSaturated(timeout), TimeUnit.NANOSECONDS);}@ParametricNullness@CanIgnoreReturnValue<T> T callUninterruptiblyWithTimeout(Callable<T> callable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException, ExecutionException;@ParametricNullness@CanIgnoreReturnValuedefault <T> T callUninterruptiblyWithTimeout(Callable<T> callable, Duration timeout) throws TimeoutException, ExecutionException {return this.callUninterruptiblyWithTimeout(callable, Internal.toNanosSaturated(timeout), TimeUnit.NANOSECONDS);}void runWithTimeout(Runnable runnable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException, InterruptedException;default void runWithTimeout(Runnable runnable, Duration timeout) throws TimeoutException, InterruptedException {this.runWithTimeout(runnable, Internal.toNanosSaturated(timeout), TimeUnit.NANOSECONDS);}void runUninterruptiblyWithTimeout(Runnable runnable, long timeoutDuration, TimeUnit timeoutUnit) throws TimeoutException;default void runUninterruptiblyWithTimeout(Runnable runnable, Duration timeout) throws TimeoutException {this.runUninterruptiblyWithTimeout(runnable, Internal.toNanosSaturated(timeout), TimeUnit.NANOSECONDS);}
}

其实现类有:

  • SimpleTimeLimiter:
  • FakeTimeLimiter:

TimeLimiter用于限制方法的执行时间,原理:

  • 创建代理对象:为指定的对象创建一个代理对象
  • 方法拦截:当调用代理对象的方法时,TimeLimiter会拦截调用,并在一个单独的线程中执行实际方法
  • 超时监控:使用定时器来监控方法的执行时间。如果方法执行超过指定的时间限制,TimeLimiter会中断该线程,并抛出一个TimeoutException

TimeLimiter可确保方法不会因为执行时间过长而阻塞其他操作。有如下使用场景:

  • 网络调用:限制网络请求的最大时间,防止由于网络延迟导致的长时间阻塞
  • 复杂计算:在后台执行复杂计算任务时,设置一个时间限制以确保任务不会无限期地运行
  • 资源获取:限制资源获取操作的时间,如数据库连接、文件读写等。

TimeLimiter的一个简单实例:

public void test() {TimeLimiter timeLimiter = SimpleTimeLimiter.create();Callable<String> callable = () -> {// Simulate long running taskThread.sleep(2000);return "Task Completed";};try {String result = timeLimiter.callWithTimeout(callable, 1, TimeUnit.SECONDS);System.out.println(result);} catch (UncheckedTimeoutException e) {// just logging or handle exception} catch (Exception e) {// just logging or handle exception}
}

TimeLimiter和RateLimiter的区别

  • 用途:TimeLimiter用于限制方法的执行时间,防止长时间运行的操作阻塞程序。RateLimiter用于限制方法的调用频率,控制流量,防止系统过载
  • 实现机制:TimeLimiter基于创建代理对象和超时监控,通过定时器中断执行时间过长的任务。RateLimiter基于令牌桶算法,通过生成和消耗令牌来控制请求的执行频率。
  • 使用场景:TimeLimiter适用于需要对单个任务的执行时间进行严格控制的场景。RateLimiter适用于需要对系统整体调用频率进行控制的场景。

Kafka

Kafka在时使用到复制限流技术,防止集群中某个主题或某个分区的流量在某段时间内特别大,分区数据复制造成数据丢失或分区节点异常。

ZooKeeper

ZK也提供一个RateLimiter的简易实现版本。

分布式限流

参考

  • 亿级流量网站架构核心技术
  • 实战Spring Cloud Gateway之限流篇

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

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

相关文章

计算机毕业设计师hadoop+spark+hive知识图谱医生推荐系统 医生数据分析可视化大屏 医生爬虫 医疗可视化 医生大数据 机器学习 大数据毕业设计

流程&#xff1a; 1.Python爬虫采集中华健康网约10万医生数据&#xff0c;最终存入mysql数据库&#xff1b; 2.使用pandasnumpy/hadoopmapreduce对mysql中的医生数据进行数据分析&#xff0c;使用高德地图解析地理位置&#xff0c;并将结果转入.csv文件同时上传到hdfs文件系统&…

百度文心智能体平台(想象即现实):轻松上手,开启智能新时代!创建属于自己的智能体应用。

目录 1.1、文心智能体平台 1.2、创建智能体 1.3、智能体报名入口 1.4、古诗词小助手 1.5、访问我的智能体 我的智能体访问地址&#xff1a;https://mbd.baidu.com/ma/s/7u8kBFYA。 在这个全新的时代里&#xff0c;人工智能技术正以前所未有的速度发展&#xff0c;渗透到我…

LinkedHashMap详解

目录 LinkedHashMap详解1、LinkedHashMap的继承体系2、LinkedHashMap的特性介绍和代码示例①、特性②、适用场景使用LinkedHashMap 实现最简单的 LRU缓存 3、LinkedHashMap的构造函数4、LinkedHashMap是如何存储元素的&#xff0c;底层数据结构是什么&#xff1f;LinkedHashMap…

用LoRA微调 Llama 2:定制大型语言模型进行问答

Fine-tune Llama 2 with LoRA: Customizing a large language model for question-answering — ROCm Blogs (amd.com) 在这篇博客中&#xff0c;我们将展示如何在AMD GPU上使用ROCm对Llama 2进行微调。我们采用了低秩适配大型语言模型(LoRA)来克服内存和计算限制&#xff0c;…

SAP赋能食品行业,确保安全与品质的双重飞跃

品安全与品质是消费者最关心的问题&#xff0c;也是食品企业的生命线。随着科技的发展和消费者需求的日益多样化&#xff0c;食品行业正面临着前所未有的挑战和机遇。SAP作为全球领先的企业资源规划&#xff08;ERP&#xff09;系统&#xff0c;为食品行业提供了全面的解决方案…

RealityCheck™电机监测和预测性维护模型

RealityCheck™电机 一个附加的软件工具箱&#xff0c;可实现条件监测和预测性维护功能&#xff0c;而无需依赖额外的传感器。相反&#xff0c;它使用来自电机控制过程的电子信息作为振动和其他传感器的代理。凭借其先进的信号处理和机器学习(ML)模型&#xff0c;RealityCheck …

惠普8596E频谱分析仪

8590E系列频谱分析仪具有各种各样的性能、功能&#xff0c;其价格亦是为适应用户的承受能力而确定的。用户可以从价格低廉、具有基本性能的分析仪直至高性能分析仪中进行挑选&#xff0c;无论选择哪种分析仪&#xff0c;都会感受到8590系列频谱分析仪便于使用且高度可靠。这些仪…

Palo Alto GlobalProtect App 6.3 (macOS, Linux, Windows, Andriod) - 端点网络安全客户端

Palo Alto GlobalProtect App 6.3 (macOS, Linux, Windows, Andriod) - 端点网络安全客户端 Palo Alto Networks 远程访问 VPN 客户端软件 请访问原文链接&#xff1a;https://sysin.org/blog/globalprotect-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。…

从0开始C++(三):构造函数与析构函数详解

目录 构造函数 构造函数的基本使用 构造函数也支持函数重载 构造函数也支持函数参数默认值 构造初始化列表 拷贝构造函数 浅拷贝和深拷贝 析构函数 总结 练习一下ヽ(&#xffe3;▽&#xffe3;)&#xff89; 构造函数 构造函数的基本使用 构造函数是一种特殊的成…

腾讯地图撒点并默认显示点位信息

实现步骤如下&#xff1a; 1、注册腾讯位置服务账号并获取 Key 2、需要创建一个地图容器&#xff0c;并使用腾讯地图的 API 初始化地图。通常涉及到设置地图的中心点、缩放级别和地图样式。 map new TMap.Map(document.getElementById(‘container’), { center: center, zo…

Vue56-组件的自定义事件

一、什么是自定义事件 二、子组件—【传值】—>父组件 2-1、prop属性 2-2、自定义事件 v-on在谁身上&#xff0c;就给谁绑定事件&#xff01; 给谁绑定的事件&#xff0c;想触发就找谁&#xff01; 2-3、prop属性VS自定义属性 2-4、简写形式 2-5、ref属性实现 加了ref属性…

软件监控发展简史

软件监控简史&#xff0c;从 00 年代开始。发生了什么变化&#xff1f;为什么事情变得如此神秘&#xff1f; 终端设备上日益重要的用户体验通过边缘计算和分布式计算不断得到改善。然而&#xff0c;服务质量的测量仍然使用基于服务器的原语进行。 我们的 2000 年软件监控是这样…

程序员兼职接单有哪些渠道?一篇文章带你了解!

2024年&#xff0c;程序员兼职接单别只盯着朋友圈啦&#xff01;这些兼职接单渠道你一个都不容错过&#xff01;想要通过兼职接单获取收入的程序员&#xff0c;一定不能错过这篇文章&#xff01; 程序员兼职接单的渠道可以简单的分类为兼职平台和程序员论坛和自身人脉拓展三个…

【SD3辅助工具推荐】InstantX发布了三种SD3专属的ControlNet模式——Pose、Canny和Tile

InstantX 是一家专注于人工智能内容生成的独立研究机构。此前&#xff0c;曾开源著名的InstantID和论文《InstantID : Zero-shot Identity-Preserving Generation in Seconds》。随着本月12号&#xff0c;Stability AI正式开源了其产品 Stable Diffusion 3&#xff0c;这家机构…

高效设计必选!5款好用的UI动效工具

UI 动态设计是应用程序设计的重要组成部分。随着技术的积累&#xff0c;UI设计中的动态效果遍地开花&#xff0c;UI动态效果可以使我们的页面更时尚、更有趣、更人性化。5G网络的快速发展也使美丽的动态效果几乎无缝地嵌入到UI界面中。今天&#xff0c;毫不夸张地说&#xff0c…

Visual Studio2022+cuda环境配置及代码调试

环境配置 下载并安装CUDA Toolkit 打开Visual Studio&#xff0c;新建项目。如下图所示&#xff0c;已经包含CUDA编程选项 代码调试 1、打开cu文件的属性页&#xff0c;按下图所示&#xff0c;将Host中的Generate Host Debug Information设置为“是" 2、不可勾选Nsight…

ARM功耗管理框架之LPI

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理框架&#xff1f;SCP&#xff1f;PPU&#xff1f;LPI&#xff1f;之间的关系&#xff1f;如何配合&#xff1f; 目录 一、功耗管理框架中的LPI 二、LPI分类 三、Q-Channel和P-Channel对比 四、Q-Channel和P-Ch…

第28讲:Ceph集群使用RBD块存储与K8S Volumes集成

文章目录 1.Ceph集群使用RBD块存储与K8S集成简介2.Ceph集群RBD块存储与K8S Volume集成2.1.在Ceph集群中创建K8S集群使用的块存储2.2.创建用于K8S访问Ceph RBD块设备的认证用户2.3.将认证用户的Key存储在K8S Secret资源中2.4.在K8S集群的所有节点中安装Ceph命令2.5.创建Pod资源使…

【uni-app学习手札】

uni-app&#xff08;vue3&#xff09;编写微信小程序 编写uni-app不必拘泥于HBuilder-X编辑器&#xff0c;可用vscode进行编写&#xff0c;在《微信开发者工具》中进行热加载预览&#xff0c; 主要记录使用uni-app过程中自我备忘一些api跟语法&#xff0c;方便以后编写查找使用…

【React 】折叠面板,点击展开时再请求数据

需求背景&#xff1a;使用折叠面板的形式展示数据&#xff0c;面板内部数据需要在打开时请求接口获取。 遇到问题&#xff1a;最开始使用Antd 的折叠面板组件&#xff0c;它对于数据直接渲染是没问题的&#xff0c;但是不好满足打开面板时再动态加载数据的需求&#xff0c;于是…