当前位置: 首页 > news >正文

分布式系统中的 ActiveMQ:异步解耦与流量削峰(二)

四、流量削峰

(一)流量削峰原理深入解析

在当今互联网应用中,高并发场景屡见不鲜 。例如,电商平台的促销活动、在线票务系统的抢票时刻以及社交平台的热点事件爆发期等,都会在短时间内迎来大量用户请求。这些瞬间涌入的海量请求,就像汹涌的潮水,给系统带来了巨大的压力。如果系统直接处理这些高并发请求,可能会因为资源耗尽而导致性能急剧下降,甚至出现系统崩溃的情况,严重影响用户体验。

ActiveMQ 作为一种消息中间件,在流量削峰方面发挥着关键作用 。其核心原理是利用消息队列作为缓冲区,将瞬间高并发产生的大量请求存储起来 。当请求到达系统时,系统不是立即处理这些请求,而是将它们封装成消息发送到 ActiveMQ 的消息队列中 。然后,系统按照自身的处理能力,从队列中逐步取出消息进行处理。这就好比水库在洪水期储存大量的水,然后在后续的时间里慢慢释放,从而避免下游河道因短时间内水量过大而决堤 。通过这种方式,ActiveMQ 有效地将高并发请求的流量进行了削峰处理,使得系统能够在自身承受范围内平稳地处理请求,保证了系统的稳定性和可靠性 。

(二)典型场景案例分析

以电商平台的秒杀活动为例,这是一个典型的高并发场景 。在秒杀活动开始的瞬间,大量用户同时点击购买按钮,向系统发送购买请求 。假设某电商平台举办一场热门手机的秒杀活动,活动开始的前 10 秒内,就收到了数百万个购买请求 。如果没有任何流量控制措施,这些请求将直接冲击系统的各个组件,包括数据库、应用服务器等 。数据库可能会因为瞬间的高并发读写操作而出现连接池耗尽、锁冲突等问题,导致查询和更新操作变得异常缓慢甚至超时 。应用服务器也可能因为线程资源被大量占用,无法及时处理新的请求,最终导致整个系统响应迟缓,页面加载缓慢,甚至出现 502、504 等错误页面,严重影响用户的购买体验,也会给电商平台带来巨大的经济损失 。

引入 ActiveMQ 后,情况得到了极大的改善 。当用户的购买请求到达系统时,系统首先将这些请求封装成消息发送到 ActiveMQ 的消息队列中 。然后,系统可以根据自身的处理能力,从队列中按一定的速率取出消息进行处理 。例如,系统每秒钟可以处理 1000 个请求,那么就可以从队列中每秒取出 1000 个消息进行后续的库存检查、订单生成等操作 。这样,即使在秒杀活动开始的瞬间有大量请求涌入,通过 ActiveMQ 的消息队列缓冲,系统也能够有条不紊地处理这些请求,避免了因瞬间高并发而导致的系统崩溃 。而且,通过合理设置队列的容量和处理速率,还可以有效地控制进入系统的请求数量,进一步保障系统的稳定运行 。

(三)代码示例与实践

以下是一个在 Java 中使用 ActiveMQ 实现流量削峰的简单代码示例,展示了如何在秒杀场景中使用 ActiveMQ 来控制请求流量 。假设我们有一个秒杀服务,当用户发起秒杀请求时,请求会被发送到 ActiveMQ 队列中,然后由消费者从队列中取出请求进行处理 。

首先,引入 ActiveMQ 的相关依赖(以 Maven 为例):

 

<dependencies>

<dependency>

<groupId>org.apache.activemq</groupId>

<artifactId>activemq-all</artifactId>

<version>5.16.3</version>

</dependency>

<dependency>

<groupId>javax.jms</groupId>

<artifactId>javax.jms-api</artifactId>

<version>2.0.1</version>

</dependency>

</dependencies>

接下来是生产者(发送秒杀请求的代码):

 

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;

public class SeckillProducer {

private static final String BROKER_URL = "tcp://localhost:61616";

private static final String QUEUE_NAME = "seckillQueue";

public static void main(String[] args) {

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

Connection connection = null;

Session session = null;

MessageProducer producer = null;

try {

// 创建连接

connection = connectionFactory.createConnection();

connection.start();

// 创建会话,第一个参数为是否支持事务,第二个参数为签收模式

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// 创建队列

Queue queue = session.createQueue(QUEUE_NAME);

// 创建消息生产者

producer = session.createProducer(queue);

// 模拟多个秒杀请求

for (int i = 0; i < 10000; i++) {

TextMessage message = session.createTextMessage("秒杀请求" + i);

producer.send(message);

System.out.println("已发送秒杀请求: " + message.getText());

}

} catch (JMSException e) {

e.printStackTrace();

} finally {

// 关闭资源

if (producer != null) {

try {

producer.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

if (session != null) {

try {

session.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

if (connection != null) {

try {

connection.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

}

}

}

在上述代码中,生产者创建了与 ActiveMQ 服务器的连接,并向名为seckillQueue的队列发送了 10000 个模拟的秒杀请求消息 。

然后是消费者(处理秒杀请求的代码):

 

import javax.jms.*;

import org.apache.activemq.ActiveMQConnectionFactory;

public class SeckillConsumer {

private static final String BROKER_URL = "tcp://localhost:61616";

private static final String QUEUE_NAME = "seckillQueue";

public static void main(String[] args) {

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(BROKER_URL);

Connection connection = null;

Session session = null;

MessageConsumer consumer = null;

try {

// 创建连接

connection = connectionFactory.createConnection();

connection.start();

// 创建会话,第一个参数为是否支持事务,第二个参数为签收模式

session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

// 创建队列

Queue queue = session.createQueue(QUEUE_NAME);

// 创建消息消费者

consumer = session.createConsumer(queue);

// 循环接收并处理消息

while (true) {

Message message = consumer.receive(1000); // 设置超时时间为1000毫秒

if (message != null && message instanceof TextMessage) {

TextMessage textMessage = (TextMessage) message;

System.out.println("已接收并处理秒杀请求: " + textMessage.getText());

// 模拟处理秒杀业务逻辑,如检查库存、生成订单等

// 这里可以添加实际的业务代码

} else {

break;

}

}

} catch (JMSException e) {

e.printStackTrace();

} finally {

// 关闭资源

if (consumer != null) {

try {

consumer.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

if (session != null) {

try {

session.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

if (connection != null) {

try {

connection.close();

} catch (JMSException e) {

e.printStackTrace();

}

}

}

}

}

消费者从seckillQueue队列中接收消息,并进行处理 。在实际应用中,还可以根据系统的处理能力和业务需求,设置队列的最大长度 。当队列满时,可以采取不同的策略来处理新的请求,比如抛弃请求并返回错误信息给用户,或者将用户请求重定向到一个提示页面,告知用户当前活动火爆,请稍后重试 。例如,可以在生产者代码中添加如下逻辑来处理队列满的情况:

 

// 假设队列最大长度为10000

int queueMaxSize = 10000;

if (queueSize >= queueMaxSize) {

// 抛弃请求,返回错误信息给用户

System.out.println("当前请求过多,请稍后重试");

// 或者跳转到错误页面

// response.sendRedirect("/errorPage");

} else {

// 发送消息到队列

producer.send(message);

}

通过以上代码示例和策略,展示了如何使用 ActiveMQ 在高并发的秒杀场景中实现流量削峰,有效地控制请求流量,保障系统的稳定运行 。

五、ActiveMQ 的配置与使用

(一)安装与部署

  1. Windows 系统
    • 下载:前往 ActiveMQ 官方网站(ActiveMQ),在下载页面找到适合 Windows 系统的二进制版本,通常为一个压缩包,如apache-activemq-x.x.x-bin.zip,这里的x.x.x代表具体版本号 。
    • 解压:将下载的压缩包解压到你希望安装 ActiveMQ 的目录,例如D:\activemq 。解压后,目录结构中bin目录包含启动和停止 ActiveMQ 的脚本文件;conf目录存放着 ActiveMQ 的各种配置文件;data目录用于存储日志等数据 。
    • 配置环境变量(可选):如果希望在任意目录下都能方便地执行 ActiveMQ 命令,可以配置环境变量。在系统环境变量中,找到Path变量,添加 ActiveMQ 的bin目录路径,如D:\activemq\bin 。
    • 启动:进入bin目录下的win64(如果是 64 位系统)或win32(32 位系统)子目录,双击activemq.bat文件即可启动 ActiveMQ 服务 。启动过程中,命令行窗口会输出启动信息,当看到类似 “INFO: ActiveMQ WebConsole available at http://localhost:8161/admin” 的提示时,说明 ActiveMQ 已成功启动 。此时,你可以通过浏览器访问http://localhost:8161/admin,进入 ActiveMQ 的管理控制台,默认用户名和密码均为admin 。
  1. Linux 系统
    • 下载:在官方网站获取 Linux 版本的 ActiveMQ 压缩包,一般为apache-activemq-x.x.x-bin.tar.gz 。
    • 解压:使用命令tar -zxvf apache-activemq-x.x.x-bin.tar.gz将压缩包解压到指定目录,例如/usr/local/activemq 。
    • 启动:进入解压后的bin目录,执行./activemq start命令即可在后台启动 ActiveMQ 。若要在前台启动并查看启动日志,可执行./activemq console命令 。启动成功后,同样可以通过浏览器访问http://服务器IP:8161/admin进入管理控制台 。
  1. 安装过程中的常见问题及解决方法
    • 端口冲突:如果启动时提示端口被占用,例如61616(ActiveMQ 默认的消息服务端口)或8161(默认的管理控制台端口)被占用 。可以修改 ActiveMQ 的配置文件来更换端口 。在conf目录下的activemq.xml文件中,找到<transportConnectors>标签,修改其中的port属性值来更改消息服务端口 ;在conf/jetty.xml文件中,找到<bean id="jettyPort"标签,修改port属性值来更改管理控制台端口 。然后重新启动 ActiveMQ 服务 。
    • JDK 版本不兼容:ActiveMQ 对 JDK 版本有一定要求,若使用的 JDK 版本不满足 ActiveMQ 的要求,可能会出现启动失败或运行异常 。请确保安装的 JDK 版本与 ActiveMQ 版本兼容,例如 ActiveMQ 5.15.0 及以上版本通常需要 JDK 8 及以上版本 。如果版本不匹配,需要升级或更换 JDK 版本 。

(二)基本配置参数说明

  1. 连接地址(Broker URL):连接地址用于指定 ActiveMQ 服务器的位置,格式通常为协议://主机:端口 。例如,默认的 TCP 连接地址tcp://localhost:61616,表示通过 TCP 协议连接到本地主机的 61616 端口 。不同的协议适用于不同的场景,TCP 协议是最常用的,它提供了高效可靠的通信 ;SSL 协议用于需要加密通信的场景,保证消息传输的安全性 ;HTTP 协议则适用于通过 Web 进行消息传输的场景 。连接地址的正确配置是客户端与 ActiveMQ 服务器建立连接的基础,若配置错误,将无法正常通信 。
  1. 用户名和密码:为了保证系统的安全性,ActiveMQ 支持设置用户名和密码进行认证 。在conf目录下的activemq.xml文件中,可以配置<simpleAuthenticationPlugin>插件来设置用户名和密码 。例如:
 

<plugins>

<simpleAuthenticationPlugin>

<users>

<authenticationUser username="admin" password="admin123" groups="admins"/>

</users>

</simpleAuthenticationPlugin>

</plugins>

上述配置中,创建了一个名为admin,密码为admin123,属于admins组的用户 。只有提供正确的用户名和密码,客户端才能连接到 ActiveMQ 服务器 。合理设置用户名和密码可以防止未经授权的访问,保护消息系统的安全 。

3. 持久化方式:ActiveMQ 支持多种消息持久化方式,以确保在服务器重启或故障时消息不会丢失 。

  • KahaDB:这是 ActiveMQ 5.4 及以上版本的默认持久化方式 。它使用文件系统来存储消息,将消息存储在data/kahadb目录下 。KahaDB 具有高性能和高可靠性的特点,适用于大多数场景 。
  • JDBC:通过 JDBC 持久化方式,ActiveMQ 可以将消息存储到关系型数据库中,如 MySQL、Oracle 等 。需要在conf/activemq.xml文件中配置数据源和持久化适配器 。例如,使用 MySQL 作为持久化数据库时,配置如下:
 

<persistenceAdapter>

<jdbcPersistenceAdapter dataSource="#mysql-ds"/>

</persistenceAdapter>

<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">

<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true"/>

<property name="username" value="root"/>

<property name="password" value="root123"/>

</bean>

JDBC 持久化方式便于与现有的数据库基础设施集成,但可能会因为数据库性能问题影响消息处理的效率 。

  • 内存(Memory):内存持久化方式将消息存储在内存中,这种方式速度非常快,但在服务器重启或故障时,内存中的消息会丢失 。适用于对消息可靠性要求不高,但对性能要求极高的场景,例如某些实时监控系统,只关注最新的消息,而不关心历史消息的持久保存 。

选择合适的持久化方式需要综合考虑系统对消息可靠性和性能的要求 。如果系统对消息可靠性要求极高,应选择 KahaDB 或 JDBC 持久化方式;如果对性能要求极高且能接受消息丢失的风险,可以选择内存持久化方式 。

(三)与 Spring Boot 整合示例

  1. 添加依赖:在 Spring Boot 项目的pom.xml文件中添加 ActiveMQ 的依赖 。如果使用 Maven 构建项目,添加以下依赖:
 

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-activemq</artifactId>

</dependency>

</dependencies>

此依赖会自动引入 ActiveMQ 与 Spring Boot 整合所需的相关库,包括 ActiveMQ 客户端、Spring JMS 相关的类等 ,方便在 Spring Boot 项目中使用 ActiveMQ 。

2. 配置文件设置:在application.properties或application.yml文件中配置 ActiveMQ 的相关参数 。以application.properties为例,配置如下:

 

spring.activemq.broker-url=tcp://localhost:61616

spring.activemq.user=admin

spring.activemq.password=admin

spring.jms.listener.container-type=default

spring.jms.listener.acknowledge-mode=auto

上述配置中,spring.activemq.broker-url指定了 ActiveMQ 服务器的连接地址;spring.activemq.user和spring.activemq.password分别是连接 ActiveMQ 服务器的用户名和密码;spring.jms.listener.container-type设置了消息监听器容器的类型为默认类型;spring.jms.listener.acknowledge-mode设置了消息的确认模式为自动确认 ,即消费者收到消息后自动向 ActiveMQ 服务器确认消息已接收 。

3. 创建消息队列:在 Spring Boot 项目中,可以通过配置类来创建消息队列 。创建一个配置类,例如ActiveMQConfig.java:

 

import org.apache.activemq.command.ActiveMQQueue;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import javax.jms.Queue;

@Configuration

public class ActiveMQConfig {

@Value("${myqueue}")

private String myQueue;

@Bean

public Queue queue() {

return new ActiveMQQueue(myQueue);

}

}

在上述配置类中,通过@Value注解从配置文件中获取队列名称myqueue,并创建一个ActiveMQQueue对象作为消息队列 。同时,在application.properties文件中添加队列名称的配置:

 

myqueue=my - activemq - queue

  1. 生产者代码编写:创建一个消息生产者类,例如MessageProducer.java:
 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jms.core.JmsMessagingTemplate;

import org.springframework.stereotype.Component;

import javax.jms.Queue;

@Component

public class MessageProducer {

@Autowired

private JmsMessagingTemplate jmsMessagingTemplate;

@Autowired

private Queue queue;

public void sendMessage(String message) {

jmsMessagingTemplate.convertAndSend(queue, message);

System.out.println("已发送消息: " + message);

}

}

在这个生产者类中,通过依赖注入获取JmsMessagingTemplate和Queue对象 。JmsMessagingTemplate是 Spring 提供的用于发送和接收消息的模板类,convertAndSend方法用于将消息发送到指定的队列中 。当调用sendMessage方法时,传入的消息会被发送到之前配置的消息队列中 。

5. 消费者代码编写:创建一个消息消费者类,例如MessageConsumer.java:

 

import org.springframework.jms.annotation.JmsListener;

import org.springframework.stereotype.Component;

@Component

public class MessageConsumer {

@JmsListener(destination = "my - activemq - queue")

public void receiveMessage(String message) {

System.out.println("已接收消息: " + message);

}

}

在消费者类中,使用@JmsListener注解来监听指定的消息队列my - activemq - queue 。当队列中有新消息到达时,receiveMessage方法会被自动调用,并将接收到的消息作为参数传入 ,在方法中可以对消息进行相应的处理 。通过以上步骤,就完成了 Spring Boot 与 ActiveMQ 的整合,实现了消息的发送和接收功能 。

六、总结与展望

ActiveMQ 作为一款强大的开源消息中间件,在分布式系统中展现出了卓越的异步解耦和流量削峰能力。通过异步通信机制,它实现了系统组件之间的解耦,使各组件能够独立发展和演化,提高了系统的灵活性和可维护性 。在高并发场景下,ActiveMQ 利用消息队列作为缓冲区,有效地进行流量削峰,保障了系统的稳定性和可靠性,为分布式系统的高效运行提供了坚实保障 。

对于开发者而言,掌握 ActiveMQ 的使用不仅能够提升系统设计和开发的能力,还能更好地应对实际项目中复杂多变的业务需求 。无论是电商、金融、物流等传统行业,还是新兴的物联网、人工智能等领域,ActiveMQ 都有着广泛的应用前景 。希望读者能够在实际项目中积极尝试应用 ActiveMQ,充分发挥其优势,解决分布式系统中的通信和性能问题 。

随着技术的不断发展,分布式系统的规模和复杂度将持续增加,对消息中间件的性能、可靠性和功能特性也将提出更高的要求 。未来,ActiveMQ 有望在性能优化、功能扩展以及与新兴技术的融合等方面取得更大的进展 。例如,在云计算和容器化技术盛行的今天,ActiveMQ 可能会进一步优化对云环境的支持,实现更便捷的部署和管理 ;在微服务架构中,它也可能会与服务治理框架进行更深度的集成,为微服务之间的通信提供更强大的支持 。让我们共同期待 ActiveMQ 在未来能够不断创新和发展,为分布式系统领域带来更多的惊喜和突破 。

相关文章:

分布式系统中的 ActiveMQ:异步解耦与流量削峰(二)

四、流量削峰 &#xff08;一&#xff09;流量削峰原理深入解析 在当今互联网应用中&#xff0c;高并发场景屡见不鲜 。例如&#xff0c;电商平台的促销活动、在线票务系统的抢票时刻以及社交平台的热点事件爆发期等&#xff0c;都会在短时间内迎来大量用户请求。这些瞬间涌入…...

JAVA设计模式——(十)抽象工厂模式(Abstract Factory Pattern)

JAVA设计模式——&#xff08;十&#xff09;抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09; 介绍理解实现工厂接口工厂实现类应用类应用类实现测试改造工厂类 应用 介绍 抽象工厂模式在工厂模式的基础上&#xff0c;适配的对象变为一组相关的对象&#xff0c…...

STM32的定时器

定时器的介绍 介绍&#xff1a;STM32F103C8T6微控制器内部集成了多种类型的定时器&#xff0c;这些定时器在嵌入式系统中扮演着重要角色&#xff0c;用于计时、延时、事件触发以及PWM波形生成、脉冲捕获等应用。 *几种定时器&#xff08;STM32F103系列&#xff09;&#xff1…...

ubuntu-PyQt5安装+PyCharm配置QtDesigner + QtUIC

个人环境 ubuntu22.04 pycharm 2024.3 python 3.10 1)先使用apt命令在线安装 1)sudo apt install pyqt5* 2)sudo apt install qttools5-dev-tools2&#xff09;Pycharm配置Pycharm External Tool 在设置—工具——外部工具中 配置QtDesigner Name &#xff1a;QtDesigne…...

测试基础笔记第十九天

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、接口的概念二、接口的类型三、接口测试1.概念2.原理&#xff1a;3.特点:4.实现方式:5.什么是自动化接口测试&#xff1f; 二、HTTP协议1.HTTP协议简介2.URL格式…...

Ubuntu 系统上广受好评的浏览器推荐

日常使用与开发者首选 Firefox 特点&#xff1a;开源、隐私保护强大&#xff0c;支持丰富扩展&#xff08;如开发者工具、广告拦截&#xff09;&#xff0c;默认预装且跨平台兼容368。 适用场景&#xff1a;日常浏览、开发者调试&#xff08;支持实时 CSS/JS 编辑&#xff09;、…...

第 13 届蓝桥杯 C++ 青少组省赛中 / 高级组真题解析

一、选择题 第 1 题 题目&#xff1a;下列关于类中声明的变量描述正确的是 ( )&#xff61; 选项&#xff1a; A. 只属于该类 B. 属于全局变量 C. 任何情况下都可被该类所有实例共享 D. 属于该类&#xff0c;某些情况下也可被该类不同实例所共享 答案&#xff1a;D 解析&…...

Win10下安装Linux-Ubuntu24.04双系统

0 引言 Ubuntu 24.04 LTS&#xff08;代号“Noble Numbat”&#xff09;是 Canonical 于 2024 年 4 月 25 日发布的第 10 个长期支持版本&#xff0c;专注于性能优化、企业安全和开发者体验提升 Windows 10 是微软于 2015 年 7 月发布的跨平台操作系统&#xff0c;融合了传统桌…...

express 怎么搭建 WebSocket 服务器

一&#xff1a;使用 express-ws var express require(express); var app express(); var expressWs require(express-ws)(app);app.use(function (req, res, next) {console.log(middleware);req.testing testing;return next(); });app.get(/, function(req, res, next){…...

模型部署——cuda编程入门

CUDA中的线程与线程束 kernel是在device上线程中并行执行的函数&#xff0c;核函数用__global__符号声明&#xff0c;在调用时需要用<<<grid_size, block_size>>>来指定kernel要执行的线程数量。在CUDA中&#xff0c;每一个线程都要执行核函数&#xff0c;并…...

llfc项目TCP服务器笔记

ChatServer 一个TCP服务器必然会有连接的接收,维持,收发数据等逻辑。那我们就要基于asio完成这个服务的搭建。主服务是这个样子的 #include "LogicSystem.h"#include <csignal>#include <thread>#include <mutex>#include "AsioIOServiceP…...

NPP库中libnppi模块介绍

1. libnppi 模块简介 libnppi 是 NPP 库中专门用于 图像处理 的模块&#xff0c;提供高度优化的 GPU 加速函数&#xff0c;支持&#xff1a; 图像滤波&#xff08;卷积、形态学操作&#xff09; 几何变换&#xff08;旋转、缩放、透视变换&#xff09; 颜色空间转换&#xf…...

从头训练小模型: 3 传统RLHF与DPO的区别

这个步骤我其实是忽略了。如果我的目标是建立一个安全领域的模型&#xff0c;我个人理解这步骤并不太必要。关于人类偏好对齐&#xff1a;在前面的训练步骤中&#xff0c;模型已经具备了基本的对话能力。 此时模型还不知道什么是好的回答&#xff0c;什么是不好的回答。我们希…...

Python-Django系列—视图

一、通用显示视图 以下两个基于类的通用视图旨在显示数据。在许多项目中&#xff0c;它们通常是最常用的视图。 1、DetailView class django.views.generic.detail.DetailView 当该视图执行时&#xff0c;self.object 将包含该视图正在操作的对象。 祖先&#xff08;MRO&a…...

el-input Vue 3 focus聚焦

https://andi.cn/page/622173.html...

动态规划(5)路径问题--剑指offer -珠宝的最大值

题目&#xff1a; 现有一个记作二维矩阵 frame 的珠宝架&#xff0c;其中 frame[i][j] 为该位置珠宝的价值。拿取珠宝的规则为&#xff1a; 只能从架子的左上角开始拿珠宝每次可以移动到右侧或下侧的相邻位置到达珠宝架子的右下角时&#xff0c;停止拿取 注意&#xff1…...

ZArchiver正版:高效文件管理,完美解压体验

在使用安卓设备的过程中&#xff0c;文件管理和压缩文件的处理是许多用户常见的需求。无论是解压下载的文件、管理手机存储中的文件&#xff0c;还是进行日常的文件操作&#xff0c;一款功能强大且操作简便的文件管理工具都能极大地提升用户体验。今天&#xff0c;我们要介绍的…...

Netlink在SONiC中的应用

Netlink在SONiC中的应用 Netlink介绍 Netlink 是 Linux 内核态程序与用户空间程序之间进行通信的机制之一&#xff0c;原本是用于传递网络协议栈中的各种控制消息。它采用和套接字&#xff08;socket&#xff09;编程接口相同的形式&#xff0c;常用于配置内核网络子系统&…...

ReentrantLock实现公平锁和非公平锁

在 Java 里&#xff0c;公平锁和非公平锁是多线程编程中用于同步的两种锁机制&#xff0c;它们的主要差异在于获取锁的顺序规则。下面是对二者的详细介绍&#xff1a; 公平锁 公平锁遵循 “先来先服务” 原则&#xff0c;也就是线程获取锁的顺序和请求锁的顺序一致。先请求锁…...

【C++】 —— 笔试刷题day_25

一、笨小猴 题目解析 这道题&#xff0c;给定一个字符str&#xff0c;让我们找到这个字符串中出现次数最多字母的出现次数maxn和出现次数最少字母的出现次数minn&#xff1b; 然后判断maxn - minn是否是一个质数&#xff0c;如果是就输出Lucky Word和maxn - minn&#xff1b;如…...

terraform resource创建了5台阿里云ecs,如要使用terraform删除其中一台主机,如何删除?

在 Terraform 中删除阿里云 5 台 ECS 实例中的某一台&#xff0c;具体操作取决于你创建资源时使用的 多实例管理方式&#xff08;count 或 for_each&#xff09;。以下是详细解决方案&#xff1a; 方法一&#xff1a;使用 for_each&#xff08;推荐&#xff09; 如果创建时使…...

Office 三大组件Excel、Word、Access 里 VBA 区别对比

以下是Excel、Word和Access在VBA中的主要区别对比及详细说明: 核心对象模型 Excel Workbook(工作簿)→ Worksheet(工作表)→ Range(单元格区域) 核心围绕单元格数据处理,如 Cells(1,1).Value = "数据" Word Document(文档)→ Range(文本范围)→ Paragrap…...

Linux 进程基础(二):操作系统

目录 一、什么是操作系统&#xff1a;用户和电脑之间的「翻译官」&#x1f310; OS 的层状结构&#x1f9e9; 案例解析&#xff1a;双击鼠标的「跨层之旅」 二、操作系统的必要性探究&#xff1a;缺乏操作系统的环境面临的挑战剖析&#x1f511; OS 的「管理者」属性&#xff1…...

Java高并发处理核心技术详解:从理论到实战

高并发处理能力是衡量系统性能的重要指标。Java作为企业级开发的主力语言&#xff0c;提供了丰富的并发编程工具和框架。 一、Java并发基础 1.1 Java内存模型&#xff08;JMM&#xff09; 主内存与工作内存&#xff1a;每个线程拥有独立的工作内存&#xff0c;通过JMM协议与主…...

单细胞测序数据分析试验设计赏析(二)

单细胞测序数据分析试验设计赏析&#xff08;二&#xff09; 这次的单细胞测序数据分析的试验设计是单细胞测序分析机器学习&#xff08;with SHAP分析&#xff09;&#xff0c;也是常见的试验设计之一&#xff0c;重点是可以用于筛选鉴定基因调控网络&#xff0c;也可以是构建…...

Docker 服务搭建

&#x1f4a2;欢迎来到张翊尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 Docker 服务搭建在 Ubuntu 上安装 Docker更新软件…...

4电池_基于开关电容的均衡

基于开关电容的均衡系统&#xff08;Switched-Capacitor Equalization System&#xff09; 开关电容均衡&#xff08;Switched-Capacitor Equalization, SCE&#xff09;是一种广泛应用于 电池组&#xff08;如锂电池、超级电容组&#xff09; 的主动均衡技术&#xff0c;通过电…...

Matlab/Simulink - BLDC直流无刷电机仿真基础教程(七) - 波形解析专题P2

Matlab/Simulink - BLDC直流无刷电机仿真基础教程&#xff08;七&#xff09; - 波形解析专题P2 前言一、缺相与相线错接解析二、电源电压波动三、电机感量及磁链变化四、负载突变及堵转五、换相时机不当及换相错误参考链接 前言 本系列文章分享如何使用Matlab的Simulink功能来…...

如何从GitHub上调研优秀的开源项目,并魔改应用于工作中?

在 Go 语言学习中&#xff0c;我们经常会去学习一些优秀的开源项目。但是学完之后&#xff0c;发现很快就忘记了或者学习效果并不好。学习一个开源项目最好的方式就是围绕这个开源项目进行实战。例如&#xff0c;直接魔改这个开源项目并应用于工作中。本文来介绍下如何调用&…...

【Java学习笔记】构造器

构造器(constructor)&#xff08;又名构造方法&#xff09; 作用&#xff1a;可以在创建对象时就初始化属性&#xff0c;注意不是创建 基本结构 [修饰符] 方法名&#xff08;形参列表&#xff09;{方法体&#xff1b; }代码示例 public class 构造器 {public static void m…...

Redis 数据类型详解(一):String 类型全解析

文章目录 前言一、什么是 Redis 的 String 类型&#xff1f;二、常用命令1.SET2.GET3.MSET4.MGET5.INCR6.INCRBY7.INCRBYFLOAT8.SETNX9.SETEX 三、注意事项总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 在学习 Redis 的过程中&#xff0c;最基础也…...

JAVA---多态

面向对象三大特征&#xff1a;封装、继承、多态 多态 定义&#xff1a;同类型的对象&#xff0c;表现出的不同形态。 它允许不同类的对象通过同一个接口进行调用&#xff0c;并且在运行时根据实际对象类型执行不同的方法。 多态主要通过继承、接口和方法重写来实现。 表现形式…...

K8S的使用(部署pod\service)+安装kubesphere图形化界面使用和操作

master节点中通过命令部署一个tomcat 查看tomcat被部署到哪个节点上 在节点3中进行查看 在节点3中进行停止容器&#xff0c;K8S会重新拉起一个服务 如果直接停用节点3&#xff08;模拟服务器宕机&#xff09;&#xff0c;则K8S会重新在节点2中拉起一个服务 暴露tomcat访…...

【Linux系统】第二节—基础指令(2)

hello ~ 好久不见 自己想要的快乐要自己好好争取&#xff01; 云边有个稻草人-个人主页 Linux—本篇文章所属专栏—欢迎订阅—持续更新中 目录 本节课核心指令知识点总结 本节基本指令详解 07.man 指令 08.cp 指令 09.mv 指令 10.cat 指令 11.more 指令 12.less 指令 …...

Java设计模式: 实战案例解析

Java设计模式: 实战案例解析 在软件开发中&#xff0c;设计模式是一种用来解决特定问题的可复用解决方案。它们是经过实践验证的最佳实践&#xff0c;能够帮助开发人员设计出高质量、易于维护的代码。本文将介绍一些常见的Java设计模式&#xff0c;并通过实战案例解析它们在实际…...

ASP.NET MVC​ 入门与提高指南九

51. 时空数据处理与 MVC 应用拓展 51.1 时空数据概念 时空数据是指与时间和空间相关的数据&#xff0c;如地理信息系统&#xff08;GIS&#xff09;数据、交通流量数据、气象数据等&#xff0c;这些数据随时间和空间变化而变化。 51.2 在 MVC 应用中处理时空数据 地理信息系…...

算法学习时段效能分布

算法学习时段效能分布 晨间时段&#xff08;06:00-09:00&#xff09;核心优势最佳任务 午后时段&#xff08;14:00-17:00&#xff09;核心优势最佳任务 夜间时段&#xff08;20:00-23:00&#xff09;核心优势最佳任务 实证数据支持 晨间时段&#xff08;06:00-09:00&#xff09…...

Linux环境部署iview-admin项目

环境&#xff1a;阿里云服务 系统&#xff1a;CentOS7.X系统 1、下载源码安装包 wget https://nodejs.org/dist/v14.17.3/node-v14.17.3-linux-x64.tar.xz2、解压并放入指定目录 tar -xf node-v14.17.3-linux-x64.tar.xz && mv node-v14.17.3-linux-x64 /usr/local/no…...

在 Ubuntu 系统中,查看已安装程序的方法

在 Ubuntu 系统中&#xff0c;查看已安装程序的方法取决于软件的安装方式&#xff08;如通过 apt、snap、flatpak 或手动安装&#xff09;。以下是几种常见方法&#xff1a; 通过 apt 包管理器安装的软件 适用于通过 apt 或 dpkg 安装的 .deb 包。 列出所有已安装的软件包&…...

c++26新功能——Pack indexing

一、模板编程 在模板编程中&#xff0c;有一个问题比较突出&#xff0c;就是对变参模板中参数的控制&#xff0c;比较麻烦。因为是变参&#xff0c;所以想把参数单独拿出来处理&#xff0c;就需要借助一些特殊的技巧&#xff0c;而这种特殊的技巧&#xff0c;往往为大多数开发…...

VSCode通过SSH连接VMware虚拟机

以下是关于VSCode通过SSH连接VMware虚拟机的原理、必要条件及注意事项的说明&#xff1a; ​​一、连接原理​ SSH协议通信​​&#xff1a;SSH&#xff08;Secure Shell&#xff09;是一种加密网络协议&#xff0c;VSCode通过Remote-SSH插件将本地开发环境与虚拟机终端绑定&a…...

7 微调 黑盒蒸馏 突破伦理限制

简介 SecGPT-Distill 是我自己做的一个实验模型, 开源地址: 主要功能是进行模型微调和知识蒸馏而来 这次是运用微调技术&#xff0c;来突破现有模型在处理安全相关问题时的各种限制和约束 代码开源: https://github.com/godzeo/SecGPT-distill-boundless 不回答原理 大部…...

基于51单片机的温湿度控制器proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1cENHPmF0XobqKg_7baZX3Q 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C51 是一款常用的 8 位单片机&#xff0c;由 Atmel 公司&#xff08;现已被 Microchip 收…...

牛客月赛115 C题-命运之弹 题解

原题链接 https://ac.nowcoder.com/acm/contest/107879/C 题目描述 解题思路 记录每个数字出现的次数。枚举使用「转瞬即逝」的位置&#xff0c;统计后边比当前数字更大的数的数量&#xff0c;进而统计、更新答案。 详细细节见代码&#xff0c;代码里有详细的注释解释。 代…...

视频转GIF

视频转GIF 以下是一个使用 Python 将视频转换为 GIF 的脚本&#xff0c;使用了 imageio 和 opencv-python 库&#xff1a; import cv2 import imageio import numpy as np """将视频转换为GIF图参数:video_path -- 输入视频的路径gif_path -- 输出GIF的路径fp…...

day15 python 复习日

作业&#xff1a; 尝试找到一个kaggle或者其他地方的结构化数据集&#xff0c;用之前的内容完成一个全新的项 目&#xff0c;这样你也是独立完成了一个专属于自己的项目。 要求&#xff1a; 1.有数据地址的提供数据地址&#xff0c;没有地址的上传网盘贴出地址即可。 2.尽可能与…...

性能优化实践:渲染性能优化

性能优化实践&#xff1a;渲染性能优化 在Flutter应用开发中&#xff0c;渲染性能直接影响用户体验。本文将从渲染流程分析入手&#xff0c;深入探讨Flutter渲染性能优化的关键技术和最佳实践。 一、Flutter渲染流程解析 1.1 渲染流水线 Flutter的渲染流水线主要包含以下几…...

【SimSession 】3:中继服务 linux和windows实现及MFC集成实现

实现目标 在 echo 测试程序启动时启动中继服务,并在 echo 程序退出时杀死中继进程。我们可以通过以下方式实现这一目标: linux设计 1 Process Management: 流程管理: Added fork() functionality to create a child process for the relay service添加了 fork()功能,…...

表驱动 FSM 在 STM32 上的高效实现与内存压缩优化——源码、性能与实践

目录 一、引言与背景 二、前提环境与依赖 三、表驱动 FSM 核心原理 四、内存压缩方案详解 4.1 稠密二维表(Dense Table) 4.2 稀疏表压缩(Sparse Table) 4.3 行压缩+Offset 4.4 位域打包(Bit‑Packing)...

windows鼠标按键自定义任意设置

因为用惯了Linux的鼠标中键的复制黏贴&#xff0c;发现windows下有完全可以实现类似自定义功能的软件&#xff0c;推荐一下&#xff1a; X Mouse Button Control。 免费版足够好用。 软件简介&#xff1a; X Mouse Button Control是一款专业的重新映射鼠标按钮的软件工具&…...