RabbitMQ(三)SpringBoot整合,可靠性投遞,死信隊列,延遲隊列,消費端限流,消息超時

文章目錄

  • 整合Springboot
    • 概述
    • 消費者
    • 生產者
  • 消息可靠性投遞
    • 故障原因
    • 解決方案
    • 生產者端消息確認機制(故障情況1)
    • 故障情況2解決方案
    • 故障情況3解決方案
  • 消費端限流
    • 概念
  • 消息超時
    • 概念
    • 隊列層面:配置隊列過期
    • 消息本身:配置消息過期
  • 死信隊列
    • 概念
    • 創建死信交換機和死信隊列
    • 創建正常隊列,綁定死信隊列
      • 代碼
  • 延遲隊列
    • 方案1:借助消息超時時間+死信隊列
    • 方案2:給RabbitMQ安裝插件
    • 檢查是否安裝
    • 測試

整合Springboot

概述

  • 搭建環境
  • 基礎設定:交換機名稱、隊列名稱、綁定關系
  • 發送消息:使用RabbitTemplate
  • 接收消息:使用@RabbitListener注解

消費者

pom

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.5</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
</dependencies>

yml

spring:rabbitmq:host: 192.168.217.134port: 5672username: guestpassword: 123456virtual-host: /
logging:level:com.atguigu.mq.listener.MyMessageListener: info

Listener

@Component
@Slf4j
public class MyMessageListener {public static final String EXCHANGE_DIRECT = "exchange.direct.order";public static final String ROUTING_KEY = "order";public static final String QUEUE_NAME = "queue.order";//    寫法一:監聽 + 在 RabbitMQ 服務器上創建交換機、隊列@RabbitListener(bindings = @QueueBinding(value = @Queue(value = QUEUE_NAME, durable = "true"),exchange = @Exchange(value = EXCHANGE_DIRECT),key = {ROUTING_KEY}))
//    寫法二:監聽
//     @RabbitListener(queues = {QUEUE_NAME})public void processMessage(String dataString, Message message, Channel channel) {log.info("消費端接收到了消息:" + dataString);}
}

生產者

pom

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.5</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency>
</dependencies>

yml

spring:rabbitmq:host: 192.168.217.134port: 5672username: guestpassword: 123456virtual-host: /

RabbitTemplate

@SpringBootTest
public class RabbitMQTest {public static final String EXCHANGE_DIRECT = "exchange.direct.order";public static final String ROUTING_KEY = "order";@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void test01SendMessage() {rabbitTemplate.convertAndSend(EXCHANGE_DIRECT, ROUTING_KEY, "Hello Rabbit!SpringBoot!");}}

消息可靠性投遞

故障原因

  1. 消息沒有發送到消息隊列上
    后果:消費者拿不到消息,業務功能缺失,數據錯誤
  2. 消息成功存入消息隊列,但是消息隊列服務器宕機了
    原本保存在內存中的消息也丟失了
    即使服務器重新啟動,消息也找不回來了
    后果:消費者拿不到消息,業務功能缺失,數據錯誤
  3. 消息成功存入消息隊列,但是消費端出現問題,例如:宕機、拋異常等等
    后果:業務功能缺失,數據錯誤

解決方案

  • 故障情況1:消息沒有發送到消息隊列
    • 解決思路A:在生產者端進行確認,具體操作中我們會分別針對交換機隊列來確認, 如果沒有成功發送到消息隊列服務器上,那就可以嘗試重新發送
    • 解決思路B:為目標交換機指定備份交換機,當目標交換機投遞失敗時,把消息投遞至備份交換機

在這里插入圖片描述

  • 故障情況2:消息隊列服務器宕機導致內存中消息丟失
    • 解決思路:消息持久化到硬盤上,哪怕服務器重啟也不會導致消息丟失
  • 故障情況3:消費端宕機或拋異常導致消息沒有成功被消費
    • 消費端消費消息成功,給服務器返回ACK信息,然后消息隊列刪除該消息
    • 消費端消費消息失敗,給服務器端返回NACK信息,同時把消息恢復為待消費的狀態,這樣就可以再次取回消息,重試一次(當然,這就需要消費端接口支持冪等性)

關聯交換機和備份交換機
在這里插入圖片描述

生產者端消息確認機制(故障情況1)

故障原因1 解決方案:消息沒有發送到消息隊列上

pom

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.5</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
</dependencies>

YAML
publisher-confirm-type,publisher-returns兩個必須要增加的配置,如果沒有則功能不生效

# producerspring:rabbitmq:host: 192.168.217.134port: 5672username: guestpassword: 123456virtual-host: /publisher-confirm-type: CORRELATED # 交換機的確認publisher-returns: true # 隊列的確認
logging:level:com.atguigu.mq.config.MQProducerAckConfig: info

創建配置類

// 用于出現推送失敗的情況下查看返回值
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;@Configuration
@Slf4j
public class RabbitConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {@Autowiredprivate RabbitTemplate rabbitTemplate;@PostConstructpublic void initRabbitTemplate() {rabbitTemplate.setConfirmCallback(this);rabbitTemplate.setReturnsCallback(this);}@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {// 消息發送到交換機成功或失敗時調用這個方法log.info("confirm() 回調函數打印 CorrelationData:" + correlationData);log.info("confirm() 回調函數打印 ack:" + ack);log.info("confirm() 回調函數打印 cause:" + cause);}@Overridepublic void returnedMessage(ReturnedMessage returned) {// 發送到隊列失敗時才調用這個方法log.info("returnedMessage() 回調函數 消息主體: " + new String(returned.getMessage().getBody()));log.info("returnedMessage() 回調函數 應答碼: " + returned.getReplyCode());log.info("returnedMessage() 回調函數 描述:" + returned.getReplyText());log.info("returnedMessage() 回調函數 消息使用的交換器 exchange : " + returned.getExchange());log.info("returnedMessage() 回調函數 消息使用的路由鍵 routing : " + returned.getRoutingKey());}
}

API說明
①ConfirmCallback接口

這是RabbitTemplate內部的一個接口,源代碼如下:

	/*** A callback for publisher confirmations.**/@FunctionalInterfacepublic interface ConfirmCallback {/*** Confirmation callback.* @param correlationData correlation data for the callback.* @param ack true for ack, false for nack* @param cause An optional cause, for nack, when available, otherwise null.*/void confirm(@Nullable CorrelationData correlationData, boolean ack, @Nullable String cause);}

生產者端發送消息之后,回調confirm()方法

  • ack參數值為true:表示消息成功發送到了交換機
  • ack參數值為false:表示消息沒有發送到交換機

②ReturnCallback接口

同樣也RabbitTemplate內部的一個接口,源代碼如下:

	/*** A callback for returned messages.** @since 2.3*/@FunctionalInterfacepublic interface ReturnsCallback {/*** Returned message callback.* @param returned the returned message and metadata.*/void returnedMessage(ReturnedMessage returned);}

注意:接口中的returnedMessage()方法僅在消息沒有發送到隊列時調用

ReturnedMessage類中主要屬性含義如下:

屬性名類型含義
messageorg.springframework.amqp.core.Message消息以及消息相關數據
replyCodeint應答碼,類似于HTTP響應狀態碼
replyTextString應答碼說明
exchangeString交換機名稱
routingKeyString路由鍵名稱

故障情況2解決方案

指定隊列名稱默認自動持久化,還可設置是否自動刪除隊列
在這里插入圖片描述

故障情況3解決方案

# consumerspring:rabbitmq:host: 192.168.217.134port: 5672username: guestpassword: 123456virtual-host: /listener:simple:acknowledge-mode: manual # 把消息確認模式改為手動確認prefetch: 1 # 每次從隊列中取回消息的數量

deliveryTag:交付標簽機制,每一個消息進入隊列時,broker都會生成一個唯一標識
在這里插入圖片描述
消息復制到各個隊列,但deliveryTag各不相同
在這里插入圖片描述

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;@Component
@Slf4j
public class MyMessageListener {public static final String QUEUE_NAME = "queue.order";public static final String QUEUE_NORMAL = "queue.normal.video";public static final String QUEUE_DEAD_LETTER = "queue.dead.letter.video";public static final String QUEUE_DELAY = "queue.test.delay";public static final String QUEUE_PRIORITY = "queue.test.priority";@RabbitListener(queues = {QUEUE_NAME})public void processMessage(String dataString, Message message, Channel channel) throws IOException {// 獲取當前消息的 deliveryTaglong deliveryTag = message.getMessageProperties().getDeliveryTag();try {// 核心操作log.info("消費端 消息內容:" + dataString);System.out.println(10 / 0);// 核心操作成功:返回 ACK 信息channel.basicAck(deliveryTag, false);} catch (Exception e) {// 獲取當前消息是否是重復投遞的//      redelivered 為 true:說明當前消息已經重復投遞過一次了//      redelivered 為 false:說明當前消息是第一次投遞Boolean redelivered = message.getMessageProperties().getRedelivered();// 核心操作失敗:返回 NACK 信息// requeue 參數:控制消息是否重新放回隊列//      取值為 true:重新放回隊列,broker 會重新投遞這個消息//      取值為 false:不重新放回隊列,broker 會丟棄這個消息if (redelivered) {// 如果當前消息已經是重復投遞的,說明此前已經重試過一次啦,所以 requeue 設置為 false,表示不重新放回隊列channel.basicNack(deliveryTag, false, false);} else {// 如果當前消息是第一次投遞,說明當前代碼是第一次拋異常,尚未重試,所以 requeue 設置為 true,表示重新放回隊列在投遞一次// 第二個參數:boolean multiple表示是否一次消費多條消息,false表示只確認該序列號對應的消息,true則表示確認該序列號對應的消息以及比該序列號小的所有消息,比如我先發送2條消息,他們的序列號分別為2,3,并且他們都沒有被確認,還留在隊列中,那么如果當前消息序列號為4,那么當multiple為true,則序列號為2、3的消息也會被一同確認。channel.basicNack(deliveryTag, false, true);}// reject 表示拒絕// 辨析:basicNack() 和 basicReject() 方法區別// basicNack()能控制是否批量操作// basicReject()不能控制是否批量操作// channel.basicReject(deliveryTag, true);}}
}

消費端限流

概念

在這里插入圖片描述
一個參數:prefetch

# consumerspring:rabbitmq:host: 192.168.217.134port: 5672username: guestpassword: 123456virtual-host: /listener:simple:acknowledge-mode: manual # 把消息確認模式改為手動確認prefetch: 1 # 每次從隊列中取回消息的數量

消息超時

概念

  • 消息設定一個過期時間,超過這個時間沒有被取走的消息就會被刪除
    • 隊列層面:在隊列層面設定消息的過期時間,并不是隊列的過期時間。意思是這
      個隊列中的消息全部使用同一個過期時間。
    • 消息本身:給具體的某個消息設定過期時間
  • 如果兩個層面都做了設置,那么哪個時間短,哪個生效

隊列層面:配置隊列過期

5000毫秒過期
在這里插入圖片描述

消息本身:配置消息過期

@SpringBootTest
public class RabbitMQTest {public static final String EXCHANGE_TIMEOUT = "exchange.test.timeout";public static final String ROUTING_KEY_TIMEOUT = "routing.key.test.timeout";@Testpublic void test04SendMessage() {// 創建消息后置處理器對象MessagePostProcessor postProcessor = message -> {// 設置消息的過期時間,單位是毫秒message.getMessageProperties().setExpiration("7000");return message;};rabbitTemplate.convertAndSend(EXCHANGE_TIMEOUT, ROUTING_KEY_TIMEOUT, "Test timeout", postProcessor);}
}

在這里插入圖片描述

死信隊列

概念

概念:當一個消息無法被消費,它就變成了死信。

  • 死信產生的原因大致有下面三種:
    • 拒絕:消費者拒接消息,basicNack()/basicReject(),并且不把消息重新放入原目標隊列,requeue=false
    • 溢出:隊列中消息數量到達限制。比如隊列最大只能存儲10條消息,且現在已經存儲 了10條,此時如果再發送一條消息進來,根據先進先出原則,隊列中最早的消息會變 成死信
    • 超時:消息到達超時時間未被消費
  • 死信的處理方式大致有下面三種:
    • 丟棄:對不重要的消息直接丟棄,不做處理
    • 入庫:把死信寫入數據庫,日后處理
    • 監聽:消息變成死信后進入死信隊列,我們專門設置消費端監聽死信隊列,做后續處理(通常采用)

創建死信交換機和死信隊列

和創建普通隊列一樣
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

創建正常隊列,綁定死信隊列

在這里插入圖片描述在這里插入圖片描述
綁定隊列到交換機
在這里插入圖片描述

代碼

@Test  
public void testSendMessageButReject() {  rabbitTemplate  .convertAndSend(  EXCHANGE_NORMAL,  ROUTING_KEY_NORMAL,  "測試死信情況1:消息被拒絕");  
}

①監聽正常隊列

@RabbitListener(queues = {QUEUE_NORMAL})
public void processMessageNormal(Message message, Channel channel) throws IOException {// 監聽正常隊列,但是拒絕消息log.info("★[normal]消息接收到,但我拒絕。");channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
}

②監聽死信隊列

@RabbitListener(queues = {QUEUE_DEAD_LETTER})
public void processMessageDead(String dataString, Message message, Channel channel) throws IOException {  // 監聽死信隊列  log.info("★[dead letter]dataString = " + dataString);log.info("★[dead letter]我是死信監聽方法,我接收到了死信消息");channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}

測試超出隊列長度進入死信隊列

@Test
public void testSendMultiMessage() {for (int i = 0; i < 20; i++) {rabbitTemplate.convertAndSend(EXCHANGE_NORMAL,ROUTING_KEY_NORMAL,"測試死信情況2:消息數量超過隊列的最大容量" + i);}
}

執行循環20次的代碼兩次
正常隊列:最大長度為10
在這里插入圖片描述

死信隊列:沒有設置最大長度,所以推送失敗的消息都進入死信隊列

在這里插入圖片描述
過一段時間正常隊列中消息超時,進入死信隊列
在這里插入圖片描述

延遲隊列

  • 方案1:借助消息超時時間+死信隊列(就是剛剛我們測試的例子)
  • 方案2:給RabbitMQ安裝插件

方案1:借助消息超時時間+死信隊列

在這里插入圖片描述

方案2:給RabbitMQ安裝插件

插件安裝
https://www.rabbitmq.com/community-plugins.html

docker inspect rabbitmqwget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v3.13.0/rabbitmq_delayed_message_exchange-3.13.0.ez
mv rabbitmq_delayed_message_exchange-3.13.0.ez /var/lib/docker/volumes/rabbitmq-plugin/_data
# 登錄進入容器內部
docker exec -it rabbitmq /bin/bash# rabbitmq-plugins命令所在目錄已經配置到$PATH環境變量中了,可以直接調用
rabbitmq-plugins enable rabbitmq_delayed_message_exchange# 退出Docker容器
exit# 重啟Docker容器
docker restart rabbitmq

檢查是否安裝

創建新交換機時可以在type中看到x-delayed-message選項
在這里插入圖片描述
在這里插入圖片描述
關于x-delayed-type參數的理解:

原本指定交換機類型的地方使用了x-delayed-message這個值,那么這個交換機除了支持延遲消息之外,到底是direct、fanout、topic這些類型中的哪一個呢?

這里就額外使用x-delayed-type來指定交換機本身的類型

測試

生產者

@Test
public void test05SendMessageDelay() {// 創建消息后置處理器對象MessagePostProcessor postProcessor = message -> {// 設置消息過期時間(以毫秒為單位)// x-delay 參數必須基于 x-delayed-message-exchange 插件才能生效message.getMessageProperties().setHeader("x-delay", "10000");return message;};// 發送消息rabbitTemplate.convertAndSend(EXCHANGE_DELAY,ROUTING_KEY_DELAY,"Test delay message by plugin " + new SimpleDateFormat("HH:mm:ss").format(new Date()),postProcessor);
}

消費者

//已創建隊列
@Component  
@Slf4j
public class MyDelayMessageListener {public static final String QUEUE_DELAY = "queue.delay.video";@RabbitListener(queues = {QUEUE_DELAY})public void process(String dataString, Message message, Channel channel) throws IOException {  log.info("[生產者]" + dataString);log.info("[消費者]" + new SimpleDateFormat("hh:mm:ss").format(new Date()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}}
//未創建情況
@Component  
@Slf4j
public class MyDelayMessageListener {  public static final String EXCHANGE_DELAY = "exchange.delay.video";public static final String ROUTING_KEY_DELAY = "routing.key.delay.video";public static final String QUEUE_DELAY = "queue.delay.video";@RabbitListener(bindings = @QueueBinding(  value = @Queue(value = QUEUE_DELAY, durable = "true", autoDelete = "false"),  exchange = @Exchange(  value = EXCHANGE_DELAY,   durable = "true",   autoDelete = "false",   type = "x-delayed-message",   arguments = @Argument(name = "x-delayed-type", value = "direct")),  key = {ROUTING_KEY_DELAY}  ))  public void process(String dataString, Message message, Channel channel) throws IOException {  log.info("[生產者]" + dataString);  log.info("[消費者]" + new SimpleDateFormat("hh:mm:ss").format(new Date()));  channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);  }  }

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19643.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19643.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19643.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++中的虛函數和純虛函數

目錄 摘要 虛函數&#xff08;Virtual Functions&#xff09; 定義 用法 純虛函數&#xff08;Pure Virtual Functions&#xff09; 定義 用法 需要避開的坑 總結 摘要 在C中&#xff0c;我們經常會在開發中使用到虛函數&#xff08;Virtual Functions&#xff09;和…

如何有效屏蔽手機上的騷擾電話20240530

如何有效屏蔽手機上的騷擾電話 引言 最近&#xff0c;我的手機經常接到954開頭的7位數字座機電話&#xff0c;這些騷擾電話讓我非常困擾。由于我經常點外賣&#xff0c;無法屏蔽所有陌生號碼&#xff0c;因此需要一個既能屏蔽特定前綴的騷擾電話&#xff0c;又不影響日常生活…

英偉達(NVIDIA)H100性能及應用場景

英偉達H100是一款性能強大的GPU芯片&#xff0c;其關鍵性能參數和應用領域可以歸納如下&#xff1a; 一、性能參數 架構&#xff1a;H100采用了新一代的Hopper架構&#xff0c;擁有高達1.8萬億次/秒的張量處理能力和高達840 TFLOPS的FP8張量性能。CUDA核心數&#xff1a;H100…

STM32學習和實踐筆記(33):待機喚醒實驗

1.STM32待機模式介紹 很多單片機具有低功耗模式&#xff0c;比如MSP430、STM8L等&#xff0c;我們的STM32也不例外。默認情況下&#xff0c;系統復位或上電復位后&#xff0c;微控制器進入運行模式。在運行模式下&#xff0c;HCLK 為CPU提供時鐘&#xff0c;并執行程序代碼。這…

kafka學習筆記06

Kafka數據存儲流程和log日志講解 講解分布式應用核心CAP知識 Kafka數據可靠性保證原理之副本機制Replica介紹《上》 Kafka數據可靠性保證原理之副本機制Replica介紹《下》 Kafka數據可靠性保證原理之ISR機制講解 Kafka的HighWatermark的作用你知道多少

暑期來臨,AI智能視頻分析方案筑牢防溺水安全屏障

隨著夏季暑期的來臨&#xff0c;未成年人溺水事故頻發。傳統的防溺水方式往往依賴于人工巡邏和警示標識的設置&#xff0c;但這種方式存在人力不足、反應速度慢等局限性。近年來&#xff0c;隨著視頻監控智能分析技術的不斷發展&#xff0c;其在夏季防溺水中的應用也日益凸顯出…

ubuntu22 搭建nginx高可用集群(VIP(keepalived) + 負載均衡)

#在所有節點安裝nginx #ps: 如果要使用tcp流轉發&#xff1a;需用二進制包安裝 make編譯時加入stream流的參數。 推薦直接安裝openresty【默認支持stream等nginx模塊&#xff0c;還附帶了很多常用的lua庫】 apt install -y net-tools sudo apt install -y nginx vim /etc/…

恒創科技:無法與服務器建立安全連接怎么解決?

在使用互聯網服務時&#xff0c;有時會出現無法與服務器建立安全連接的問題&#xff0c;此錯誤消息通常出現在嘗試訪問需要安全連接的網站(例如使用 HTTPS 的網站)時&#xff0c;這可能是由于多種原因造成的&#xff0c;以下是一些常見的解決方法&#xff0c;幫助你解決問題。 …

聚道云軟件連接器:打通易快報與保融資金系統,實現高效財務管理

一、客戶介紹&#xff1a;食品企業&#xff0c;引領健康零食新風尚 某食品行業的公司作為國內領先的集研發、生產、銷售為一體的現代化辣味休閑食品企業。該公司秉承“健康、美味、安全”的理念&#xff0c;不斷創新和進取&#xff0c;為消費者帶來了一系列美味可口的辣味休閑…

msvcp100.dll丟失怎樣修復?幾種快速有效修復msvcp100.dll丟失的方法

在使用電腦時是不是遇到過關于msvcp100.dll丟失文件丟失的情況&#xff1f;出現這樣的情況有什么辦法可以將丟失的msvcp100.dll文件快速恢復&#xff1f;今天的這篇文章就將教大家幾種能夠有效的解決msvcp100.dll丟失問題的方法。 方法一&#xff1a;重啟電腦 重啟電腦是一種簡…

參數高效微調PEFT(三)快速入門LoRA、AdaLoRA

參數高效微調PEFT(三)快速入門LoRA、AdaLoRA 我們已經了解了HuggingFace中peft庫的幾種高效微調方法。 參數高效微調PEFT(一)快速入門BitFit、Prompt Tuning、Prefix Tuning 參數高效微調PEFT(二)快速入門P-Tuning、P-Tuning V2 今天我們繼續了解大火的高效微調方法LoRA以及…

MyBatis基礎理解教程,詳細分步基礎查詢表數據練習(通俗易懂、實時更新)

一、MyBatis是什么 MyBatis 是一個持久層框架&#xff0c;簡化JDBC開發&#xff0c;它提供了一個從 Java 應用程序到 SQL 數據庫的橋梁&#xff0c;用于數據的存儲、檢索和映射。MyBatis 支持基本的 SQL 操作、高級映射特性以及與 Maven 等構建工具的集成。 二、持久層是什么…

IDEA增加.gitignore文件后的處理

IDEA增加 .gitignore 文件后&#xff0c;但還是被 git 跟蹤了。 我的文件已經被添加到 .gitignore 中&#xff0c;但仍然被 Git 跟蹤&#xff0c; 文件被修改后commint中就會存在此文件。 原因: 文件已經被提交過了 如果文件在添加到 .gitignore 之前已經被提交到 Git 倉庫中,…

Spring boot集成通義千問大模型

Spring boot集成通義千問大模型 背景 我在用idea進行java開發時發現了通義靈碼這款免費的智能代碼補全插件&#xff0c;用了一段時間了&#xff0c;感覺很不錯。就想著在自己的項目中也能集成通義千問大模型實現智能回答&#xff0c;畢竟對接openai需要解決網絡問題&#xff…

戰略合作 | 竹云賦能雁塔區數字經濟高質量發展

2024年5月30日&#xff0c;由西安市數據局指導&#xff0c;中共西安市雁塔區委、西安市雁塔區人民政府主辦的 “雁塔區企業數字化轉型發展大會” 在西安開幕。 本次活動以“數智雁塔&#xff0c;引領未來”為主題&#xff0c;特邀業內150余位政府、數字化服務企業、傳統行業企…

Kubernetes 之 DaemonSet 基本原理

Kubernetes 之 DaemonSet 基本原理 DaemonSet 定義 DaemonSet 確保全部&#xff08;或者某些&#xff09;節點上運行一個 Pod 的副本。 當有節點加入集群時&#xff0c; 也會為他們新增一個 Pod 。 當有節點從集群移除時&#xff0c;這些 Pod 也會被回收。刪除 DaemonSet 將會…

先導微型數控桌面式加工中心

隨著數控技術、傳感器技術、人工智能等技術的不斷發展&#xff0c;制造業的快速發展和技術的不斷進步&#xff0c;小型五軸加工中心的性能將不斷提升&#xff0c;五軸聯動技術作為解決異性復雜零件高效優質加工問題的重要手段&#xff0c;使其具有更廣泛的應用前景。小型五軸加…

【啟明智顯分享】國產自主ZX7981P Wi-Fi6 5G-CPE開發板有哪些優勢?

在當前競爭激烈的智能設備市場中&#xff0c;高性能與低功耗的開發板已然成為各大產品追求的關鍵優勢。 今天我們從國產自主研發的ZX7981P Wi-Fi6 5G-CPE開發板的特點出發&#xff0c;分析他是否滿足市場追求的特點。 主要特點&#xff1a; 1. 強大配置&#xff0c;穩定可靠 …

5.30 學習總

刷題記錄(Codeforces Round 947 &#xff08;Div. 1 Div. 2&#xff09;B,C題)和Codeforces Round 948 &#xff08;Div. 2&#xff09;B題 一.B. 378QAQ and Mochas Array B. 378QAQ and Mochas Array time limit per test 1 second memory limit per test 256 megabytes in…

長難句5.30

Researchers measured people’s cortisol, which is a stress marker, while they were at work and while they were at home and found it higher at what is supposed to be a place of refuge. 研究人員測量了人們在工作中和在家里的皮質醇(壓力的一種標志)&#xff0c;結…