SpringBoot集成-RocketMQ快速入门

news/2024/12/21 22:39:55/

1.MQ概述

MQ全称为Message Queue,即消息队列 ,是一种提供消息队列服务的中间件,也称为消息中间件,是一套提供了消息生 产、存储、消费全过程的软件系统,遵循FIFO原则。

1.1MQ常见产品

  • ActiveMQ
    ActiveMQ是使用Java语言开发一款MQ产品。早期很多公司与项目中都在使用。但现在的社区活跃度已 经很低。现在的项目中已经很少使用了。
  • RabbitMQ
    RabbitMQ是使用ErLang语言开发的一款MQ产品。其吞吐量较Kafka与RocketMQ要低,且由于其不是 Java语言开发,所以公司内部对其实现定制化开发难度较大。
  • Kafka
    Kafka是使用Scala/Java语言开发的一款MQ产品。其最大的特点就是高吞吐率,常用于大数据领域的实 时计算、日志采集等场景。其没有遵循任何常见的MQ协议,而是使用自研协议。对于Spring Cloud Netflix,其仅支持RabbitMQ与Kafka。
  • RocketMQ
    RocketMQ是使用Java语言开发的一款MQ产品。经过数年阿里双11的考验,性能与稳定性非常高。其 没有遵循任何常见的MQ协议,而是使用自研协议。对于Spring Cloud Alibaba,其支持RabbitMQ、 Kafka,但提倡使用RocketMQ

1.2MQ作用

  • 限流削峰
    MQ可以将系统的超量请求暂存其中,以便系统后期可以慢慢进行处理,从而避免了请求的丢失或系统 被压垮。
  • 异步&解耦
    上游系统对下游系统的调用若为同步调用,则会大大降低系统的吞吐量与并发度,且系统耦合度太高。 而异步调用则会解决这些问题。所以两层之间若要实现由同步到异步的转化,一般性做法就是,在这两层间添加一个MQ层。 即使消费者挂掉也不影响生产者工作,只要把消息放入队列即可,消费者重启后自己消费即可。
  • 数据收集
    分布式系统会产生海量级数据流,如:业务日志、监控数据、用户行为等。针对这些数据流进行实时或 批量采集汇总,然后对这些数据流进行大数据分析,这是当前互联网平台的必备技术。通过MQ完成此 类数据收集是最好的选择。
  • 大数据处理
    比如我们的平台向“三方平台”获取数据,一次请求了大量数据回来要进行处理,由于数据较多处理不过来,那么就可以放入MQ,再创建一些消费者进行数据处理即可。

2.RocketMQ

2.1概述

RocketMQ是一个统一消息引擎、一种提供消息队列服务的中间件,轻量级数据处理平台。 RocketMQ是⼀款阿⾥巴巴开源的消息中间件,阿⾥巴巴向 Apache 软件基⾦会捐赠 RocketMQ

2.2RocketMQ安装

2.2.1下载

下载地址:http://rocketmq.apache.org/release_notes/release-notes-4.2.0/

下载后解压

  • Bin : 可执行文件目录
  • Conif:配置文件目录
  • Lib : 依赖库,一堆Jar包
2.2.2配置环境变量

2.3启动RocketMQ

2.3.1启动NameServer(注册中心)

Cmd命令框执行进入至MQ文件夹\bin下,然后执行 start mqnamesrv.cmd,启动NameServer。

成功后会弹出提示框,此框勿关闭。

2.3.2启动Broker

CMD执行start mqbroker.cmd -n 127.0.0.1:9876 autoCreateTopicEnable=true ,启动Broker。

成功后会弹出提示框,此框勿关闭

2.4RocketMQ本地存储结构

RabbitMQ安装好之后会在用户目录下产生一个store目录用来存储相关数据:

  • Commitlog : 消息是存储,在commitlog目录中,以mapperdFile文件顺序存储消息。
  • Config : 存放运行期间的配置文件
  • Consumerqueue : 该目录中存放的是队列,consume queue存放着commitlog中的消息的索引位置
  • Index :存放着消息索引文件 indexFile,用来实现根据key进行消息的快速查询
  • Abort : 该文件在broker启动后自动创建,正常关闭abort会消失
  • Checkpoint :记录 Commitlog ,Consumerqueue 和index 文件的最后刷盘时间戳

[]RocketMQ数据存储在磁盘会影响性能吗?

不会,RocketMQ的性能在所有的MQ中是比较高的,主要是因为RocketMQ使用了mmap零拷贝技术,consumequeue中的数据是顺序存放的,还引入了PageCache的预读取机制,使得对 consumequeue文件的读取几乎接近于内存读取,即使在有消息堆积情况下也不会影响性能。

2.5安装可视化界面

2.5.1下载

RocketMQ可视化管理插件下载地址:https://github.com/apache/rocketmq-externals/releases

2.5.2修改配置

解压后,修改配置:src/main/resource/application.properties ,这里需要指向Name Server 的地址和端口 如下:

2.5.3打包插件

回到安装目录(pom.xml所在目录),执行: mvn clean package -Dmaven.test.skip=true ,然后会在target目录生成打包后的jar文件

2.5.4启动插件

进入 target 目录,执行 java -jar rocketmq-console-ng-1.0.0.jar , 访问 http://localhost:8080

3.RocketMQ原理

3.1RocketMQ组成

RocketMQ的集群架构如下

3.1.1Producer

消息发布的角色,支持分布式集群方式部署。Producer启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,并获取当前Broker的ip和端口号等信息,轮负载均衡算法从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。

3.1.2Consumer

Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息

3.1.3NameServer

NameServer是一个Broker与Topic路由的注册中心支持Broker的动态注册与发现,NameServer等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。

  • Broker管理
    NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活。
  • 路由信息管理
    每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费
3.1.4Broker

Broker主要负责消息的存储、投递和查询以及服务高可用保证,每个Broker集群节点进行横向扩展,即将Broker节点再建为一个HA集群,解决单点问题。

Broker节点集群是一个主从集群,即集群中具有Master与Slave两种角色。Master负责处理读写操作请求,Slave负责对Master中的数据进行备份。当Master挂掉了,Slave则会自动切换为Master去工作。所以这个Broker集群是主备集群。Consumer既可以从Master订阅消息,也可以从Slave订阅消息。一个Master可以包含多个Slave,但一个Slave只能隶属于一个Master。 Master与Slave 的对应关系是通过指定相同的BrokerName、不同的BrokerId 来确定的。BrokerId为0表示Master非0表示Slave。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。

3.1.5Topic主题

一个Broker中有多个Topic,每条message消息只能属于一个topic主题,Topic用来区分不同的消息,消费者根据Topic来选择需要消费的消息,Topic中包含queue队列(默认四个),生产者发送消息时根据负载均衡算法选择其中一个队列发送

3.1.6Tag标签
  • Tag是附加在Topic上的一个二级分类标签,可以理解为Topic内部的一个子类别或子主题。
  • 作用:同一个Topic下的消息可以通过不同的Tag进一步细分,以便于更细致地管理和消费消息。每个消息在发布时都可以携带一个或多个Tag。

Topic与Tag的关系

  1. 一对多:一个Topic可以有多个Tag,也就是说,在一个大的主题下,可以根据业务需求划分出多个子类别的消息。
3.1.7MessageQueue队列

一个Topic中可以包含多个Queue(默认四个),一 个Topic的Queue也被称为一个Topic中消息的分区(Partition)。 在一个Consumer Group内,一个Queue最多只能分配给一个Consumer,一个Cosumer可以分配得到多个Queue。这样的分配规则,每个Queue只有一个消费者,可以避免消费过程中的多线程处理和资源锁定,有效提高各Consumer消费的并行度和处理效率。

【注意】 一个Topic可以对应多个消费者 ,一个Queue只能对应一个组中的一个消费者。

【注意】为了防止消息紊乱,一个Consumer Group 中的Consumer都是订阅相同Topic下的Queue。

3.2RocketMQ工作原理

3.2.1工作流程
  1. 启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。
  2. Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
  3. 收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。
  4. Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,负载均衡算法从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。
  5. Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息
3.2.2Producer 生产者
3.2.2.1消息发送方式

同步发送、异步发送、顺序发送、单向发送

3.2.2.2生产者组(解决单点故障)

生产者组是同一类生产者的集合,这类Producer发送相同Topic类型的消息。一个生产者组可以同时发送多个主题的消息。

3.2.2.3消息选择队列算法

轮询算法:挨个选择分配

消息发送延迟最低算法:根据消息发送到每个队列中的时间,按照延迟最低选择

3.2.3Consumer 消费者
3.2.3.1消费者组(解决单点故障)

消费者组是同一类消费者的集合,这类Consumer消费的是同一个Topic类型的消息,不同的 Consumer Group可以消费同一个Topic。一个Consumer Group内的Consumer可以消费多个Topic的消息。

3.2.3.2消费者消息拉取模式

消息的消费分为:拉取式 pull(消费者主动拉取) ,和推送是 push(NameServer主动发送给消费者)

  • Pull:拉取式,需要消费者间隔一定时间就去遍历关联的Queue,实时性差但是便于应用控制消息的拉取
  • Push:默认推送式,封装了Queue的遍历,实时性强,但是对系统资源占用比较多。
3.2.3.3Queue的分配算法

Queue是如何分配给Consumer的,这对应了四种算法:平均分配策略,环形平均策略,一致性Hash策略,同机房策略。

  • 平均分配(轮询)【默认】:根据 qeueuCount / consumerCount 作为每个消费者平均分配数量,如果多出来的queue就再依次逐个分配给Consumer(顺序不固定)。
  • 环形平均策略:根据消费者的顺序,顺时针一个一个的分配Queue即可类似于发扑克牌,完全平均(顺序也是固定)。
  • 一致性Hash策略 : 该算法将Consumer的Hash值作为节点放到Hash环上,然后将Queue的hash值也放入Hash环上,通过顺时针进行就近分配。
  • 同机房策略:该算法会根据queue的部署机房位置和consumer的位置,过滤出当前consumer相同机房的queue。然后按照平均分配策略或环形平均策略对同机房queue进行分配。如果没有同机房queue,则按照平均分配策略或环形平均策略对所有queue进行分配。

平均分配性能比较高,一致性Hash性能不高,但是能减少Rebalance,如果Consumer数量变动频繁可以使用一致性Hash。

3.2.3.4消息消费模式

消息的消费模式有广播模式和集群模式

  • 广播模式:同一个Consumer Group 下的所有Consumer都会受到同一个Topic的所有消息。同一个消息可能会被消费多次
  • 集群模式(默认):同一个Gonsumer Group 下的Consumer平分同一个Topic下的消息。同一个消息只是被消费一次
3.2.3.5Rebalance重新负载

当消费者数量或者Queue的数量修改,Rebalance是把⼀个Topic下的多个Queue重新分配给Consumer Group下的Consumer。目的是增加消费能力。

由于一个队列只分配给一个Consumer,那么当Consumer Group中的消费者数量大于队列数量,那么多出来的Consumer分配不到队列。

3.2.3.6Offset标记
3.2.3.6.1概述

RockertMQ通过Offset来维护Consumer的消费进度,比如:消费者从哪个位置开始持续消费消息的?这里有三个枚举来指定从什么位置消费

  • CONSUME_FROM_LAST_OFFSET:从queue的最后一条消息开始消费
  • CONSUME_FROM_FIRST_OFFSET:从queue的第一条消息开始消费
  • CONSUME_FROM_TIMESTAMP:从某个时间戳位置的消息开始消费
3.2.3.6.2Offset原理

Broker将消息队列分为一个环形,每次消费都从Offset开始,消费者消费结束之后,会向Consumer会提交其消费进度offset给Broker。Offset信息的存储分为本地 Offset管理 和远程Offset管理

  • 远程Offset管理:Brocker通过 store/config/consumerOffset.json 文件以JSON方式来存储offset相关数据以json的形式:适用于集群模式
  • 本地Offset管理:offset相关数据以json的形式持久化到Consumer本地磁盘文件中,路径为当前用户主目录下的.rocketmq_offsets/{group}/Offsets.json :适用于广播模式
3.2.3.6.3Offset提交方式

Offset的同步提交与异步提交: 集群消费模式下,Consumer消费完消息后会向Broker提交消费进度offset,其提交方式分为两种:

  • 同步提交:消费者在消费完一批消息后会向broker提交这些消息的offset,等待broker的成功响应。若在等待超时之前收到了成功响应,则继续读取下一批消息进行消费(从ACK中获取 nextBeginOffset)。若没有收到响应,则会重新提交,直到获取到响应。而在这个等待过程中,消费 者是阻塞的。其严重影响了消费者的吞吐量。
  • 异步提交:消费者在消费完一批消息后向broker提交offset,但无需等待Broker的成功响应,可以继续读取并消费下一批消息。这种方式增加了消费者的吞吐量。但需要注意,broker在收到提交的offset 后,还是会向消费者进行响应的。可能还没有收到ACK,此时Consumer会从Broker中直接获取 nextBeginOffset。
3.2.4消息的清理

消息不会被单独清理,消息是顺序存储到commitlog的,消息是以commitlog为单位进行清理,RocketMQ有自己的清理规则,默认是72小时候后进行清理

  • 到达时间清理点,自动清理过期的文件(凌晨4点)
  • 磁盘空间使用率达到了过期清理阈值(75%),自动清理过期的文件。
  • 磁盘占用率达到清理阈值(85%),开始按照设定的规则清理文件,从老的文件开始。
  • 磁盘占用率达到系统危险阈值(90%),拒绝写入数据。

4.SpringBoot集成RocketMq

4.1导包

<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><!-- <version>2.0.4</version> --><version>2.2.1</version>
</dependency>

4.2配置yml文件

rocketmq:name-server: 127.0.0.1:9876#生产者配置producer:#生产者组名字group: "service-producer"# 消息最大长度 默认 1024 * 1024 * 4 (4M)max-message-size: 4194304# 发送消息超时时间,默认 3000send-message-timeout: 3000# 发送消息失败重试次数,默认2retry-times-when-send-failed: 2# 异步消息发送失败重试次数retry-times-when-send-async-failed: 2#达到 4096 ,进行消息压缩compress-message-body-threshold: 4096consumer:#消费者名字group: "service-consumer"#批量拉取消息数量pull-batch-size: 10message-model: CLUSTERINGselector-expression: "*"

4.3创建生产者

4.3.1注入rocketMQTemplate
java">@Autowired
private RocketMQTemplate rocketMQTemplate;
4.3.2发送消息
4.3.2.1发送同步消息

同步消息是发送者发送消息,需要等待结果的返回,才能继续发送第二条消息,这是一种阻塞式模型,虽然消息可靠性高,但是阻塞导致性能低。

java">/*** 同步消息** @throws Exception 异常*/@Testpublic void syncMessage() throws Exception {Message<String> message = MessageBuilder.withPayload("你好呀!哈哈123").build();SendResult sendResult = rocketMQTemplate.syncSend("cctv-topic:cctv6-tag", message);if (!sendResult.getSendStatus().equals(SendStatus.SEND_OK)) {System.err.println("发送失败");}}
4.3.2.2发送异步消息

异步消息是发送者发送消息,无需等待发送结果就可以再发送第二条消息,它是通过回调的方式来获取到消息的发送结果,消息可靠性高,性能也高。

java">/*** 异步消息** @throws Exception 异常*/@Testpublic void asyncMessage() throws Exception {Message<String> message = MessageBuilder.withPayload("你好呀!我是异步消息").build();rocketMQTemplate.asyncSend("cctv-topic:cctv6-tag", message, new SendCallback() {/*** 成功** @param sendResult 发送结果*/@Overridepublic void onSuccess(SendResult sendResult) {if (!SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {System.err.println("发送失败");}System.out.println(sendResult);}/*** 在异常** @param throwable throwable*/@Overridepublic void onException(Throwable throwable) {System.out.println("发送异常");throwable.printStackTrace();}});Thread.sleep(5000);}
4.3.2.3发送单向消息

这种方式指的是发送者发送消息后无需等待Broker的结果返回,Broker也不会返回结果,该方式性能最高,但是消息可靠性低。

java"> /*** 单向信息*/@Testpublic void oneWayMessage() {Message<String> message = MessageBuilder.withPayload("你好呀!我是单向消息").build();rocketMQTemplate.sendOneWay("cctv-topic:cctv6-tag", message);}
4.3.2.4发送延迟消息

延迟消息即:把消息写到Broker后需要延迟一定时间才能被消费 , 在RocketMQ中消息的延迟时间不能任意指定,而是由特定的等级(1 到 18)来指定,分别有:

messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

可以通过修改配置来增加级别,比如在mq安装目录的 broker.conf 文件中增加

messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 2d 这个时候总共就有19个level。

java"> /*** 延迟消息*/@Testpublic void deferredMessage() {Message<String> message = MessageBuilder.withPayload("你好呀!我是延迟消息").build();//发送延迟消息,单位毫秒,2秒超时,延迟30秒SendResult sendResult = rocketMQTemplate.syncSend("cctv-topic:cctv6-tag", message, 2000, 4);if (!SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {System.err.println("发送失败");}}
4.3.2.5发送顺序消息
4.3.2.5.1发送全局顺序消息

全局有序是一个topic下的所有消息都要保证顺序,如果要保证消息全局顺序消费,就需要保证使用一个队列存放消息,一个消费者从这一个队列消费消息就能保证顺序,即:单线程执行。

java">/*** 全局顺序信息*/@Testpublic void sequentialMessage() {for (int i = 0; i < 5; i++) {Message<String> message = MessageBuilder.withPayload("你好呀!我是顺序消息,我是第---" + i + "---个").build();//发送延迟消息,单位毫秒,2秒超时,延迟30秒SendResult sendResult = rocketMQTemplate.syncSend("order-topic:order-tag", message);if (!SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {System.err.println("发送失败");}}}
4.3.2.5.2发送局部顺序消息

还有一种就是分区有序或者部分有序,部分顺序消息只要保证某一组消息被顺序消费,即:只需要保证一个队列中的消息有序消费即可。

hashKey: hashKey 是一个字符串类型的参数,它用于计算消息应该被路由到哪个Message Queue。RocketMQ使用哈希算法对hashKey进行计算,将同一hashKey对应的消息都路由到同一个Message Queue上,这样可以确保具有相同hashKey的所有消息按发送顺序依次消费。

java">  /*** 部分有序消息*/@Testpublic void partiallyOrderedMessage() {for (int i = 1; i < 5; i++) {for (int j = 1; j < 5; j++) {Message<String> message = MessageBuilder.withPayload("你好呀!我是局部有序消息" + i + "组中的第" + j + "条").build();SendResult sendResult = rocketMQTemplate.syncSendOrderly("partially-topic:partially-tag", message, String.valueOf(i));if (!sendResult.getSendStatus().equals(SendStatus.SEND_OK)) {System.err.println("发送失败");}}}}
4.3.2.6事务消息
4.3.2.7死信队列

消息多次消费失败,达到最大重试次数,消息不会被丢弃而是进入死信队列(Dead-Letter Queue,DLQ),死信队列中的消息被称为死信消息(Dead-Letter Message,DLM)。

死信队列具有如下特征

  • 死信队列中的消息无法再消费,死信队列对应Topic的权限为2,只有写权限,所以死信队列没有办法读取。
  • 3天之后死信队列分钟的消息被删除,和普通消息一样
  • 死信队列就是一个特殊的Topic,名称为%DLQ%consumerGroup@consumerGroup,其中每个队列都是死信队列
  • 如果⼀个消费者组未产生死信消息,则不会为其创建相应的死信队列

如果出现死信队列,说明程序除了问题,程序员应该及时的排除,进行BUG的处理。我们应该在消费者重试次数达到一定程度就对消息进行持久化,方便后续的处理。或额外定时重试。

4.4创建消费者

4.4.1普通消费者
java">@Component
@RocketMQMessageListener(topic = "cctv-topic",consumerGroup = "cctv-consumer",selectorExpression = "cctv6-tag")
public class CctvConsumer implements RocketMQListener<MessageExt> {@Overridepublic void onMessage(MessageExt message) {byte[] body = message.getBody();System.out.println(new String(body, StandardCharsets.UTF_8));}
}
  • RocketMQListener : MQ提供了的消费者监听器,MessageExt是消息对象Message的子类 。这里的泛型对应生产者的消息类型,可以直接是消息的对象类型。
  • @RocketMQMessageListener: 消息监听的注解,提供了常用的四个属性
  •    consumerGroup :消费者的组名
  • topic : 主题,对应生产者发送消息指定的destination拼接的主题
  • selectorExpression :消息选择表达式,其实就是制定消费什么tags ; 可以是固定一个值,如果是 * 是消费该topic下的所有消息 ;或者可以使用:   tag1 | tag2 的方式 消费多个消息,除此之外还支持使用SQL进行消息过滤,这种方式可以实现对消息的复杂过滤。SQL过滤表达式中支持多种常量类型与运算符。比如:and ; or ; not ; IS NULL 或者 IS NOT NULL 等等。
  • messageModel :消息的消费模式,默认是CLUSTERING集群,还支持BROADCASTING广播
4.4.2顺序消息消费者
java">/*** 部分有序消费** @author * @date 2024/01/21*/
@Component
@RocketMQMessageListener(topic = "partially-topic",consumerGroup = "partially-consumer",selectorExpression = "partially-tag",consumeMode = ConsumeMode.ORDERLY
)
public class PartiallyConsumer implements RocketMQListener<MessageExt> {@Overridepublic void onMessage(MessageExt message) {byte[] body = message.getBody();System.out.println(new String(body, StandardCharsets.UTF_8));}
}

http://www.ppmy.cn/news/1534369.html

相关文章

水波荡漾效果+渲染顺序+简单UI绘制

创建场景及布置 创建新场景Main,在Main场景中创建一个plane物体&#xff0c;命名为WaterWavePla,具体数值及层级面板排布如下&#xff1a; 编写脚本 创建一个文件夹&#xff0c;用于存放脚本&#xff0c;命名Scripts,创建一个子文件夹Effect,存放特效相关脚本&#xff0c;创建…

第二十三节:学习拦截器或者使用AOP实现用户token参数请求检测(自学Spring boot 3.x的第六天)

这节记录下如何使用aop或者使用interceptor实现用户请求的是否带token&#xff0c;本文只是简单检查用户请求是否带参数token&#xff0c;并不对token的正确性进行验证。通常要从后台缓存中进行token校验。 第一种方式&#xff1a;拦截器方式 第一步&#xff1a;新建一个拦截器…

论文翻译 | LLaMA-Adapter :具有零初始化注意的语言模型的有效微调

摘要 我们提出了一种轻量级的自适应方法&#xff0c;可以有效地将LLaMA微调为指令遵循模型。lama - adapter采用52K自指导演示&#xff0c;在冻结的LLaMA 7B模型上只引入1.2M可学习参数&#xff0c;在8个A100 gpu上进行微调花费不到一个小时。具体来说&#xff0c;我们采用了一…

Windows 环境上安装 NASM 和 YASM 教程

NASM 和 YASM NASM NASM&#xff08;Netwide Assembler&#xff09;是一个开源的、可移植的汇编器&#xff0c;它支持多种平台和操作系统。它可以用来编写16位、32位以及64位的代码&#xff0c;并且支持多种输出格式&#xff0c;包括ELF、COFF、OMF、a.out、Mach-O等。NASM使用…

linux和windows系统使用k8s控制节点的kubernetes资源

一般linux获取master控制节点的授权&#xff1a; [rootharbor ~]# vim /etc/hosts 192.168.1.30 harbor 192.168.1.50 master 192.168.1.51 node-0001 192.168.1.52 node-0002 192.168.1.53 node-0003 192.168.1.54 node-0004 192.168.1.55 node-0005#下…

Linux之Docker虚拟化部署

上传docker安装包 解压安装包 将解压后的docker文件夹移动到/usr/local/文件夹下 docker 启动命令/usr/local/docker/dockerd 但是启动报错&#xff0c;意思是没有docker用户组 创建docker用户组&#xff0c;执行完会生成套接字文件 将套接字文件加入该用户组管理 第二个错误原…

【Linux】进程概念-2

文章目录 1.环境变量1.1 基本概念1.2 常见环境变量1.3 查看环境变量方法1.4 测试PATH1.5 测试HOME1.6 和环境变量相关的命令1.7 环境变量的组织方式1.8 通过代码如何获取环境变量1.9 通过系统调用获取或设置环境变量1.10 环境变量通常是具有全局属性的1.11 实验 2. 程序地址空间…

HarmonyOS Next应用开发——响应式布局之媒体查询

响应式布局之媒体查询 媒体查询作为响应式设计的核心&#xff0c;在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式&#xff0c;常用于多屏幕的应用适配。媒体查询常用于下面两种场景&#xff1a; 针对设备和应用的属性信息&#xff08;…