电商系统秒杀三 秒杀兜底方案之熔断降级

一 秒杀场景介绍

1.1 秒杀场景的特点

1、秒杀具有瞬时高并发的特点,秒杀请求在时间上高度集中于某一特定的时间点(秒杀开始那一秒),这样一来,就会导致一个特别高的流量峰值,它对资源的消耗是瞬时的。
2、但是对秒杀这个场景来说,最终能够抢到商品的人数是固定的,也就是说 100 人和 10000 人发起请求的结果都是一样的,并发度越高,无效请求也越多。
3、但是从业务上来说,秒杀活动是希望更多的人来参与的,也就是开始之前希望有更多的人来刷页面,但是真正开始下单时,秒杀请求并不是越多越好。

1.2 流量消峰

服务器的处理资源是恒定的,你用或者不用它的处理能力都是一样的,所以出现峰值的话,很容易导致忙到处理不过来,闲的时候却又没有什么要处理。流量削峰,一是可以让服务端处理变得更加平稳,二是可以节省服务器的资源成本。针对秒杀这一场景,削峰从本质上来说就是更多地延缓用户请求的发出,以便减少和过滤掉一些无效请求,它遵从“请求数要尽量少”的原则。流量削峰的比较常见的思路:排队、答题、分层过滤。

1.3 兜底方案

对于很多秒杀系统而言,在诸如双十一这样的大流量的迅猛冲击下,都曾经或多或少发生过宕机的情况。当一个系统面临持续的大流量时,它其实很难单靠自身调整来恢复状态,你必须等待流量自然下降或者人为地把流量切走才行,这无疑会严重影响用户的购物体验。
我们可以在系统达到不可用状态之前就做好流量限制,防止最坏情况的发生。针对秒杀系统,在遇到大流量时,更多考虑的是运行阶段如何保障系统的稳定运行,常用的手段:限流,降级,拒绝服务。

二 限流实战

限流相对降级是一种更极端的保存措施,限流就是当系统容量达到瓶颈时,我们需要通过限制一部分流量来保护系统,并做到既可以人工执行开关,也支持自动化保护的措施。

限流既可以是在客户端限流,也可以是在服务端限流。限流的实现方式既要支持 URL 以及方法级别的限流,也要支持基于 QPS 和线程的限流。

客户端限流

  • 好处:可以限制请求的发出,通过减少发出无用请求从而减少对系统的消耗。
  • 缺点:当客户端比较分散时,没法设置合理的限流阈值:如果阈值设的太小,会导致服务端没有达到瓶颈时客户端已经被限制;而如果设的太大,则起不到限制的作用。

服务端限流

  • 好处:可以根据服务端的性能设置合理的阈值
  • 缺点:被限制的请求都是无效的请求,处理这些无效的请求本身也会消耗服务器资源。

在限流的实现手段上来讲,基于 QPS 和线程数的限流应用最多,最大 QPS 很容易通过压测提前获取,例如我们的系统最高支持 1w QPS 时,可以设置 8000 来进行限流保护。线程数限流在客户端比较有效,例如在远程调用时我们设置连接池的线程数,超出这个并发线程请求,就将线程进行排队或者直接超时丢弃。

限流必然会导致一部分用户请求失败,因此在系统处理这种异常时一定要设置超时时间,防止因被限流的请求不能 fast fail(快速失败)而拖垮系统。

限流的方案

  • 前端限流
  • 接入层nginx限流
  • 网关限流
  • 应用层限流

2.1 nginx限流

https://nginx.org/en/docs/

# window下nginx强制关闭命令
taskkill /fi "imagename eq nginx.EXE" /f
# 启动nginx
start nginx.exe
# 重新加载配置
nginx.exe -s reload

limit_conn_zone&limit_conn
ngx_http_limit_conn_module 可以对于一些服务器流量异常、负载过大,甚至是大流量的恶意攻击访问等,进行并发数的限制;该模块可以根据定义的键来限制每个键值的连接数,只有那些正在被处理的请求(这些请求的头信息已被完全读入)所在的连接才会被计数。

# 限制连接数
limit_conn_zone $binary_remote_addr zone=addr:10m;server {location /download/ {# 指定每个给定键值的最大同时连接数,同一IP同一时间只允许有1个连接limit_conn addr 1;}

客户端的IP地址作为键。
binary_remote_addr变量的长度是固定的4字节,存储状态在32位平台中占用32字节或64字节,在64位平台中占用64字节。
1M共享空间可以保存3.2万个32位的状态,1.6万个64位的状态。
如果共享内存空间被耗尽,服务器将会对后续所有的请求返回 503 (Service Temporarily Unavailable) 错误。

缺陷: 前端做LVS或反向代理,会出现大量的503错误,需要设置白名单(对某些ip不做限制)

limit_req_zone&limit_req
通过ngx_http_limit_req_module 模块可以通过定义的键值来限制请求处理的频率。特别的,可以限制来自单个IP地址的请求处理频率。 限制的方法如同漏斗,每秒固定处理请求数,推迟过多请求

http {# 限制请求数,大小为10m(兆), 平均处理的频率不能超过每秒1次limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;...server {...location /search/ {# 允许超出频率限制的请求数为5(多出来的5个令牌作为备用),默认会被延迟处理,如果不希望延迟处理,可以使用nodelay参数limit_req zone=one burst=5 nodelay;}

区域名称为one,大小为10M,平均处理的请求频率不能超过每秒一次。键值是客户端IP。
在这里插入图片描述

使用$binary_remote_addr变量,可以将每条状态记录的大小减少到64个字节,这样1M的内存可以保存大约1万6千个64字节的记录
如果限制域的存储空间耗尽了,对于后续所有请求,服务器都会返回503(Service Temporarily Unavailable)错误
速度可以设置为每秒处理请求数和每分钟处理请求数,其值必须是整数,所以如果你需要每秒处理少于1个的请求,2秒处理一个请求,可以使用30r/m

测试:
在这里插入图片描述
利用Lua限流

https://github.com/openresty/lua-resty-limit-traffic

2.2 网关限流

spring cloud gateway接入Sentinel实现限流的原理:
在这里插入图片描述

2.2.1 网关接入sentinel控制台

建议sentinel 控制台和微服务sentinel版本一一对应,否则可能出现兼容性问题导致规则配置失效

引入依赖

<!--添加Sentinel的依赖-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency><!-- gateway接入sentinel  -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

接入sentinel控制台,修改application.yml配置

spring:application:name: tulingmall-gatewaymain:allow-bean-definition-overriding: truecloud:sentinel:transport:dashboard: 127.0.0.1:8000

启动sentinel控制台

java  -Dserver.port=8000 -Dsentinel.nacos.config.serverAddr=tl.nacos.com:8848 -jar sentinel-dashboard-1.7.1.jar

网关接入控制台后界面展示:
在这里插入图片描述
Sentinel1.7.1版本,gateway网关规则不生效的问题
根本原因: SlotChain中没有添加GatewayFlowSlot ,默认生效的是HotParamSlotChainBuilder

在这里插入图片描述
解决思路: 使用GatewaySlotChainBuilder,将GatewayFlowSlot加入到SlotChain
可以利用SPI实现:在当前微服务添加GatewaySlotChainBuilder的spi文件

在这里插入图片描述
Sentinel1.8.0 中SlotChain处理策略,统一在DefaultSlotChainBuilder中处理了
在这里插入图片描述

2.2.2 Sentinel规则持久化配置

在这里插入图片描述
引入依赖

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

application.yml添加datasource配置

spring:cloud:sentinel:transport:# 添加sentinel的控制台地址dashboard: 127.0.0.1:8000datasource:     gateway-flow-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-gateway-flow-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: gw-flowgateway-api-rules:nacos:server-addr: 127.0.0.1:8848dataId: ${spring.application.name}-gateway-api-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: gw-api-group

启动持久化改造后的sentinel dashboard

指定端口和nacos配置中心地址

java  -Dserver.port=8000 -Dsentinel.nacos.config.serverAddr=tl.nacos.com:8848 -jar tuling-sentinel-dashboard.jar

注意:网关规则改造的坑

  1. 网关规则实体转换
RuleEntity---》Rule  利用RuleEntity#toRule
#网关规则实体
ApiDefinitionEntity---》ApiDefinition   利用ApiDefinitionEntity#toApiDefinition
GatewayFlowRuleEntity----->GatewayFlowRule   利用GatewayFlowRuleEntity#toGatewayFlowRule
  1. json解析丢失数据
    json解析ApiDefinition类型出现数据丢失的现象 天坑
    在这里插入图片描述

排查原因: ApiDefinition的属性Set predicateItems中元素 是接口类型,JSON解析丢失数据
在这里插入图片描述
解决方案:重写实体类ApiDefinition2,再转换为ApiDefinition

//GatewayApiRuleNacosProvider.java@Override
public List<ApiDefinitionEntity> getRules(String appName,String ip,Integer port) throws Exception {String rules = configService.getConfig(appName + NacosConfigUtil.GATEWAY_API_DATA_ID_POSTFIX,NacosConfigUtil.GROUP_ID, NacosConfigUtil.READ_TIMEOUT);if (StringUtil.isEmpty(rules)) {return new ArrayList<>();}// 注意 ApiDefinition的属性Set<ApiPredicateItem> predicateItems中元素 是接口类型,JSON解析丢失数据// 重写实体类ApiDefinition2,再转换为ApiDefinitionList<ApiDefinition2> list = JSON.parseArray(rules, ApiDefinition2.class);return list.stream().map(rule ->ApiDefinitionEntity.fromApiDefinition(appName, ip, port, rule.toApiDefinition())).collect(Collectors.toList());
}public class ApiDefinition2 {private String apiName;private Set<ApiPathPredicateItem> predicateItems;public ApiDefinition2() {}public String getApiName() {return apiName;}public void setApiName(String apiName) {this.apiName = apiName;}public Set<ApiPathPredicateItem> getPredicateItems() {return predicateItems;}public void setPredicateItems(Set<ApiPathPredicateItem> predicateItems) {this.predicateItems = predicateItems;}@Overridepublic String toString() {return "ApiDefinition2{" + "apiName='" + apiName + '\'' + ", predicateItems=" + predicateItems + '}';}public ApiDefinition toApiDefinition() {ApiDefinition apiDefinition = new ApiDefinition();apiDefinition.setApiName(apiName);Set<ApiPredicateItem> apiPredicateItems = new LinkedHashSet<>();apiDefinition.setPredicateItems(apiPredicateItems);if (predicateItems != null) {for (ApiPathPredicateItem predicateItem : predicateItems) {apiPredicateItems.add(predicateItem);}}return apiDefinition;}
}

从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:

  • route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
  • 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组

route维度限流

配置流控规则
在这里插入图片描述
测试:
在这里插入图片描述
配置流控规则

API维度限流
在这里插入图片描述
在这里插入图片描述

2.3 应用层限流

场景: 商品详情接口
系统第一次上线启动,或者系统在 redis 故障的情况下重新启动,这时在高并发的场景下就会出现所有的流量 都会打到mysql(原始数据库) 上去,导致 mysql 崩溃。因此需要通过缓存预热的方案,提前给 redis 灌入部分数据后再提供服务。
jemeter测试: 模拟2秒内查询商品id为1-5000的商品信息
/pms/productInfo/${__counter(,)}

在这里插入图片描述
压测直接访问DB的接口: 吞吐量: 20-60

public PmsProductParam getProductInfo1(Long id){PmsProductParam productInfo = portalProductDao.getProductInfo(id);if(null == productInfo){return null;}checkFlash(id, productInfo);return productInfo;
}

在这里插入图片描述
压测访问缓存的接口:

public PmsProductParam getProductInfo2(Long id) {PmsProductParam productInfo = null;// 查询本地缓存productInfo = cache.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id);if (null != productInfo) {return productInfo;}// 查询redis缓存productInfo = redisOpsUtil.get(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, PmsProductParam.class);if (productInfo != null) {//设置本地缓存cache.setLocalCache(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, productInfo);return productInfo;}// 查询DBproductInfo = portalProductDao.getProductInfo(id);if (null == productInfo) {return null;}checkFlash(id, productInfo);// 设置redis缓存redisOpsUtil.set(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, productInfo, 3600, TimeUnit.SECONDS);// 设置本地缓存cache.setLocalCache(RedisKeyPrefixConst.PRODUCT_DETAIL_CACHE + id, productInfo);return productInfo;
}

第一次访问缓存击穿的吞吐量: 20-60

之后吞吐量: 1000-2800
在这里插入图片描述
思考: 在没有事先进行缓存预热的情况下,如何避免更多的请求直接访问到数据库?

当对数据库访问达到阈值,可以对商品详情请求限流
配置流控规则
在这里插入图片描述
思考:排队等待可以应用于什么场景?
匀速排队(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER)方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法。
该方式的作用如下图所示:
在这里插入图片描述
这种方式主要用于处理间隔性突发的流量,例如消息队列。想象一下这样的场景,在某一秒有大量的请求到来,而接下来的几秒则处于空闲状态,我们希望系统能够在接下来的空闲期间逐渐处理这些请求,而不是在第一秒直接拒绝多余的请求。

注意:匀速排队模式暂时不支持 QPS > 1000 的场景。

场景: 对秒杀接口进行流控
在这里插入图片描述
在这里插入图片描述
热点参数限流
何为热点?热点即经常访问的数据。商家不定期做一些“商品秒杀”、“商品推广”活动,导致“营销活动”、“商品详情”、“交易下单”等链路应用出现 缓存热点访问 的情况:

  • 活动时间、活动类型、活动商品之类的信息不可预期,导致 缓存热点访问 情况不可提前预知;
  • 缓存热点访问 出现期间,应用层少数 热点访问 key 产生大量缓存访问请求,冲击分布式缓存系统,大量占据内网带宽,最终影响应用层系统稳定性;

很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。 热点key
在这里插入图片描述
注意:

  1. 热点规则需要使用@SentinelResource(“resourceName”)注解,否则不生效
  2. 参数必须是7种基本数据类型才会生效

在这里插入图片描述
配置热点参数限流规则
在这里插入图片描述
测试: http://localhost:8866/pms/productInfo/26
在这里插入图片描述
思考: 如何快速且准确的发现热点访问key ? 不可预测的热点key 热点探测(网关层)

热点探测功能设计思路

在这里插入图片描述

三 降级实战

降级就是当系统的容量达到一定程度时,限制或者关闭系统的某些非核心功能,从而把有限的资源保留给更核心的业务。

比如降级方案可以这样设计:当秒杀流量达到 5w/s 时,把成交记录的获取从展示 20 条降级到只展示 5 条。“从 20 改到 5”这个操作由一个开关来实现,也就是设置一个能够从开关系统动态获取的系统参数。

降级的核心目标是牺牲次要的功能和用户体验来保证核心业务流程的稳定,是一个不得已而为之的举措。例如在双 11 零点时,如果优惠券系统扛不住,可能会临时降级商品详情的优惠信息展示,把有限的系统资源用在保障交易系统正确展示优惠信息上,即保障用户真正下单时的价格是正确的。

3.1 服务降级的策略

https://www.processon.com/view/link/60dc6e485653bb2a8d08850d
在这里插入图片描述

3.2 应用层降级实战

场景: 秒杀下单 /order/miaosha/generateOrder
在这里插入图片描述
如果会员服务出现问题,会影响整个下单链路。
模拟查询会员地址信息出现网络问题和业务异常

@ApiOperation("显示收货地址详情")
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
@ResponseBody
public CommonResult<UmsMemberReceiveAddress> getItem(@PathVariable Long id,@RequestHeader("memberId") long memberId) {if(memberId==3){try {//模拟网络问题Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}if(memberId==4){//模拟业务异常throw new IllegalArgumentException("非法参数异常");}UmsMemberReceiveAddress address = memberReceiveAddressService.getItem(id,memberId);return CommonResult.success(address);
}

测试: memberId为3的用户压测
在这里插入图片描述
Sentinel熔断降级
OpenFeign整合Sentinel
配置文件打开 Sentinel 对 Feign 的支持:feign.sentinel.enabled=true

feign:sentinel:enabled: true

feign接口配置fallbackFactory

@FeignClient(name = "tulingmall-member",path = "/member",fallbackFactory = UmsMemberFeginFallbackFactory.class)
public interface UmsMemberFeignApi {

UmsMemberFeginFallbackFactory中编写降级逻辑

@Component
public class UmsMemberFeginFallbackFactory implements FallbackFactory<UmsMemberFeignApi> {@Overridepublic UmsMemberFeignApi create(Throwable throwable) {return new UmsMemberFeignApi() {@Overridepublic CommonResult<UmsMemberReceiveAddress> getItem(Long id) {//TODO 业务降级UmsMemberReceiveAddress defaultAddress = new UmsMemberReceiveAddress();defaultAddress.setName("默认地址");defaultAddress.setId(-1L);defaultAddress.setDefaultStatus(0);defaultAddress.setPostCode("-1");defaultAddress.setProvince("默认省份");defaultAddress.setCity("默认city");defaultAddress.setRegion("默认region");defaultAddress.setDetailAddress("默认详情地址");defaultAddress.setMemberId(-1L);defaultAddress.setPhoneNumber("199xxxxxx");return CommonResult.success(defaultAddress);}@Overridepublic CommonResult<String> updateUmsMember(UmsMember umsMember) {return null;}@Overridepublic CommonResult<PortalMemberInfo> getMemberById() {return null;}@Overridepublic CommonResult<List<UmsMemberReceiveAddress>> list() {return null;}};}
}

会员收货地址接口配置基于响应时间的降级规则
在这里插入图片描述
测试
在这里插入图片描述
会员收货地址接口配置基于异常数的降级规则
在这里插入图片描述
测试
在这里插入图片描述

四 拒绝服务

拒绝服务可以说是一种不得已的兜底方案,用以防止最坏情况发生,防止因把服务器压跨而长时间彻底无法提供服务。当系统负载达到一定阈值时,例如 CPU 使用率达到 90% 或者系统 load 值达到 2*CPU 核数时,系统直接拒绝所有请求,这种方式是最暴力但也最有效的系统保护方式。

例如秒杀系统,我们可以在以下环节设计过载保护:

  • 在最前端的 Nginx 上设置过载保护,当机器负载达到某个值时直接拒绝 HTTP 请求并返回 503 错误码。
    阿里针对nginx开发的过载保护扩展插件sysguard: https://github.com/alibaba/nginx-http-sysguard

  • 在 Java 层同样也可以设计过载保护。 比如Sentinel提供了系统规则限流

Sentinel系统规则限流
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

  • Load 自适应(仅对 Linux/Unix-like 机器生效):系统的 load1 作为启发指标,进行自适应系统保护。当系统 load1 超过设定的启发值,且系统当前的并发线程数超过估算的系统容量时才会触发系统保护(BBR 阶段)。系统容量由系统的 maxQps * minRt 估算得出。设定参考值一般是 CPU cores * 2.5。
  • CPU usage(1.5.0+ 版本):当系统 CPU 使用率超过阈值即触发系统保护(取值范围 0.0-1.0),比较灵敏。
  • 平均 RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
  • 并发线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
  • 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。

系统规则持久化yml配置

system-rules:nacos:server-addr: tl.nacos.com:8848dataId: ${spring.application.name}-system-rulesgroupId: SENTINEL_GROUPdata-type: jsonrule-type: system

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

LATTICE进阶篇DDR2--(1)获取官网DDR2例程并仿真

前言 本章主要讲述如何从官网下载DDR2的DEMO例程&#xff0c;并将例程的仿真运行起来。 官网的DEMO在Diamond工程里是没有调用任何任何IP核的&#xff0c;只是在仿真的时候调用了CORE文件夹下的IP核源文件进行仿真&#xff0c;该DEMO工程主要是拿来产生仿真波形&#xff0c;对…

算法学习——LeetCode力扣图论篇2

算法学习——LeetCode力扣图论篇2 1020. 飞地的数量 1020. 飞地的数量 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相…

这回轮到鸿蒙禁用安卓了!!!

1月18日&#xff0c;鸿蒙生态千帆仪式上&#xff0c;华为正式宣布了HarmonyOS NEXT&#xff08;下简称鸿蒙星河版或纯血鸿蒙&#xff09;开发者预览已向开发者开放申请&#xff0c;纯血鸿蒙开始走向普及阶段。伴随着不再兼容安卓的纯血鸿蒙铺开&#xff0c;鸿蒙走进了运营属于自…

本地虚拟机服务器修改站点根目录并使用域名访问的简单示例

说明&#xff1a;本文提及效果是使用vmware虚拟机&#xff0c;镜像文件是Rocky8.6 一、配置文件路径 1. /etc/httpd/conf/httpd.conf #主配置文件 2. /etc/httpd/conf.d/*.conf #调用配置文件 调用配置文件的使用&#xff1a; vim /etc/httpd/conf.d/webpage.conf 因为在主配…

python opencv之提取轮廓并拟合圆

图片存储地址为&#xff1a;C:\Users\Pictures\test.png&#xff0c;该图像图片背景是黑色的&#xff0c;目标区域是亮的&#xff0c;目标区域是两段圆弧和两段曲线构成的封闭区域&#xff0c;其中两段圆弧属于同一个圆&#xff0c;但在目标区域的相对位置&#xff0c;也就是不…

CrossOver软件2024免费 最新版本详细介绍 CrossOver软件好用吗 Mac电脑玩Windows游戏

CrossOver是一款由CodeWeavers公司开发的软件&#xff0c;它可以在Mac和Linux等操作系统上运行Windows软件&#xff0c;而无需在计算机上安装Windows操作系统。这款软件的核心技术是Wine&#xff0c;它是一种在Linux和macOS等操作系统上运行Windows应用程序的开源软件。 Cross…

Linux系统---如何理解Linux中的文件系统

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、理解文件系统 1.ls与stat 我们使用ls -l的时候看到的除了看到文件名&#xff0c;还看到了文件元数据。 每行包含7列…

rabbitMQ版本问题与下载

都到现在了&#xff0c;大家不会安装东西还是不看版本吧 云服务器买的是centos7&#xff0c;而erlang在24版本后不支持centos7了 所以需要找24版本以下的erlang&#xff0c;而不同erlang对应不同rabbitmq所以需要对应 下载erlang 说实话&#xff0c;自己安装&#xff0c;还是…

前端小白如何理解mvc mvp mvvm

架构、框架、设计模式是都是啥&#xff1f; 架构&#xff1a;抽象出来不同组织或者对象亦或是简单组件&#xff0c;根据需求和各个单元的功能&#xff0c;进行组合排列。 从而完成系统的运行或者是实现目标。 框架&#xff1a;使用什么样的规则&#xff0c;什么样的开发语言&…

个人用户免费,亚马逊正式推出 AI 编程服务 CodeWhisperer

IT之家消息 亚马逊于 2022 年 6 月以预览版的形式&#xff0c;推出了 AI 辅助编程服务 CodeWhisperer。2023年4 月 14 日宣布该服务正式上线&#xff0c;并免费向个人用户开放。点击亚马逊云科技可以注册使用 CodeWhisperer是一种人工智能&#xff08;基于机器学习&#xff09…

消息队列的七种经典应用场景

在笔者心中&#xff0c;消息队列&#xff0c;缓存&#xff0c;分库分表是高并发解决方案三剑客。 在职业生涯中&#xff0c;笔者曾经使用过 ActiveMQ 、RabbitMQ 、Kafka 、RocketMQ 这些知名的消息队列 。 这篇文章&#xff0c;笔者结合自己的真实经历&#xff0c;和大家分享…

搜索与图论——染色法判定二分图

一个图是二分图当且仅当这个图中不含奇数环 由于图中没有奇数环&#xff0c;所以染色过程中一定没有矛盾 所以一个二分图一定可以成功被二染色&#xff0c;反之在二染色的过程中出现矛盾的图中一定有奇数环&#xff0c;也就一定不是二分图 #include<iostream> #includ…

http和https的工作原理是什么?

HTTP&#xff08;HyperText Transfer Protocol&#xff09;和HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是两种用于在互联网上传输数据的主要协议&#xff0c;它们均用于在客户端&#xff08;通常是Web浏览器&#xff09;与服务器之间交换信息。尽管它们…

NSSCTF Round#20 Basic 真亦假,假亦真 CSDN_To_PDF V1.2 出题笔记 (附wp+源码)

真亦假&#xff0c;假亦真 简介&#xff1a;java伪造php一句话马。实则信息泄露一扫就出&#xff0c;flag在/flag里面。 题目描述&#xff1a;开开心心签个到吧&#xff0c;祝各位师傅们好运~ 静态flag&#xff1a;NSS{Checkin_h4v3_4_g00D_tINNe!} /路由显示 <?php e…

Radash一款JavaScript最新的实用工具库,Lodash的平替!

文章目录 Lodash 的痛点进入正题--Radash特点 举例几个常用的api 一说lodash应该大部分前端同学都知道吧&#xff0c;陪伴我们好多年的JavaScript工具库&#xff0c;但是自从 ES6 出现后就慢慢退出前端人的视线&#xff0c;能ES6写的代码绝对不会用Lodash&#xff0c;也不是完全…

住宅IP是什么?与机房IP有哪些区别?

随着互联网的普及和发展&#xff0c;不同类型的IP地址在网络世界中扮演着重要角色。在网络架构中&#xff0c;机房IP和住宅IP是两种常见的IP类型&#xff0c;它们各有优劣&#xff0c;适用于不同的场景和需求。本文将对机房IP和住宅IP进行技术对比&#xff0c;并给出选择合适IP…

vue项目使用eletron将打包成桌面应用(.exe)

vue项目使用eletron将打包成桌面应用(.exe) 1.前期准备 两个项目&#xff1a; 1、自己用vue cli创建的项目 2、第二个是去gitee将案例clone下来 案例地址 https://gitee.com/qingplus/electron-quick-start.git 2、测试案例是否可以正常运行 # 进入项目 cd electron-quick-…

kubernetes负载均衡资源-Ingress

一、Ingress概念 1.1 Ingress概念 使用NodePort类型的Service可以将集群内部服务暴露给集群外部客广端,但使用这种类型Service存在如下几个问题。 1、一个端口只能一个服务使用,所有通过NodePort暴露的端口都需要提前规划;2、如果通过NodePort暴露端口过多,后期维护成本太…

IPv6-重定向,PMTU,GRE隧道

IPv6-重定向&#xff0c;PMTU&#xff08;路径最大传输单元&#xff09;&#xff0c;GRE隧道&#xff08;Generic Routing Encapsulation&#xff0c;通用路由封装协议&#xff09; 重定向过程 触发重定向的条件&#xff1a; 1、报文的入接口&#xff0c;等于自身路由之后的…

ubuntu2204配置zabbix6.4高可用

zabbix6.4-HA 配置keepalived配置haproxy数据库高可用配置zabbix-server配置proxy配置客户端agent 本实验VMware搭建zabbix6.4高可用集群&#xff0c;搭配haproxykeepalived。 master&#xff0c;node节点搭建haproxykeepalibed主备并配置vip地址 三台控制节点搭建数据库高可用…