RabbitMQ RPC模式Python示例

文章目錄

  • 1.服務端
  • 2.客戶端
  • 3.調用結果

1.服務端

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@File:      rabbitmq_server.py
@Date:      2025/6/26 10:42
@Author:    xxx
@Description:
1. RabbitMQ服務端,支持多節點命令執行
2. 作為被控節點運行,可接收定向命令并返回結果
"""import ssl
import pika
import time
import json
import socket
import logging
import subprocess
import configparser# 定義日志模塊
logger = logging.getLogger()
# 設置全局日志級別設為最低(DEBUG)
# # 可選: DEBUG, INFO, WARNING, ERROR, CRITICAL
logger.setLevel(logging.DEBUG)# 1. 文件日志(僅輸出到文件)
file_handler = logging.FileHandler('rabbitmq_server.log', encoding='utf-8')
file_handler.setLevel(logging.DEBUG)  # 文件記錄DEBUG及以上級別
file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(lineno)04d - %(message)s', datefmt="%Y-%m-%d %H:%M:%S"))
logger.addHandler(file_handler)# 2. 控制臺日志(僅輸出到控制臺)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)  # 控制臺僅顯示INFO及以上
console_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(lineno)04d - %(message)s', datefmt="%Y-%m-%d %H:%M:%S"))
logger.addHandler(console_handler)RABBITMQ_HOST_CONF = "/etc/rabbitmq/rabbitmq.conf"class RabbitMQServer:"""RabbitMQ RPC服務器類功能:接收并執行來自客戶端的定向命令"""def __init__(self, node_name=None, mq_user="rabbitmq", mq_password="rabbitmq@123",mq_virtual_host="/", mq_host=None, mq_port=5671,mq_ca="/opt/ssl/ca_certificate.pem"):"""初始化RabbitMQ服務端:param node_name: 節點名稱標識(唯一):param mq_user: RabbitMQ用戶名:param mq_password: RabbitMQ密碼:param mq_virtual_host: 虛擬主機:param mq_host: RabbitMQ服務器IP:param mq_port: RabbitMQ服務端口:param mq_ca: SSL證書路徑"""# 節點配置self.NODE_NAME = node_name if node_name else socket.gethostname()# 連接配置self.RABBITMQ_USER = mq_userself.RABBITMQ_UNLOCK_CODE = mq_passwordself.RABBITMQ_VIRTUAL_HOST = mq_virtual_host# 如果沒有設置RabbitMQ服務器IP,則連接到配置文件中設置的IP節點self.RABBITMQ_HOST = mq_host if mq_host else self.get_option(RABBITMQ_HOST_CONF, "global", "rabbitmq_host")self.RABBITMQ_PORT = mq_portself.SSL_CA_PATH = mq_ca# 初始化連接self._setup_connection()def get_option(self, file_path, section, option):"""獲取 file_path 配置項值,若配置文件沒有,返回空字符串:param section: section字符串,例如:'global':param option: key值,例如:'manage_nodes':return: 字符串類型數據"""parser = configparser.ConfigParser()parser.read(file_path)if not parser.has_option(section, option):return ""else:return parser.get(section, option)def _get_ssl_options(self):"""配置SSL安全連接選項"""# 創建一個 SSL/TLS 安全通信的上下文對象# 生產環境建議指定協議版本,避免使用不安全的默認值context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)# 在 SSL/TLS 通信中承擔核心安全驗證功能context.load_verify_locations(self.SSL_CA_PATH)# 創建 RabbitMQ 的 SSL 連接配置對象return pika.SSLOptions(context,        # ssl.SSLContext 對象,包含證書、協議版本等SSL配置# TODO 可以根據具體證書,設置該選項"localhost"     # 服務器主機名,用于證書驗證(需匹配證書CN或SAN字段),主機名驗證:強制檢查證書中的 CN(Common Name) 或 SAN(Subject Alternative Name) 是否匹配"localhost")def _setup_connection(self):"""建立RabbitMQ連接并設置隊列"""# 創建 RabbitMQ 連接所需的用戶名/密碼認證對,用于后續建立連接時的身份驗證credentials = pika.PlainCredentials(self.RABBITMQ_USER,         # RabbitMQ 服務認證用戶名(字符串類型)self.RABBITMQ_UNLOCK_CODE   # RabbitMQ 服務認證密碼(字符串類型))# RabbitMQ 連接參數設置connection_params = pika.ConnectionParameters(# RabbitMQ服務器IP地址(字符串類型)# - 若未配置則自動讀取配置文件中的虛擬IP# - 示例:'192.168.120.19' 或 'rabbitmq.example.com'host=self.RABBITMQ_HOST,# RabbitMQ服務端口(整數類型)# - 默認使用加密端口5671# - 非加密連接通常用5672port=self.RABBITMQ_PORT,# 虛擬主機名稱(字符串類型)# - 默認'/'表示根虛擬主機# - 用于多租戶隔離場景virtual_host=self.RABBITMQ_VIRTUAL_HOST,# 認證憑證對象(pika.PlainCredentials)# - 包含用戶名/密碼信息# - 必須與RabbitMQ配置的用戶權限匹配credentials=credentials,# SSL配置對象(pika.SSLOptions)# - 包含CA證書和主機名驗證配置# - 為空時建立非加密連接ssl_options=self._get_ssl_options(),# 心跳檢測間隔(秒,整數類型),建議設置為300-1200秒(防止NAT超時斷開)# - 600秒=10分鐘檢測一次連接活性# - 0表示禁用心跳(不推薦)heartbeat=600   # 需 ≥ 客戶端配置)# 建立與 RabbitMQ 服務器的同步阻塞式連接# 阻塞式:所有操作(如發送/接收消息)會阻塞當前線程直到完成self.connection = pika.BlockingConnection(connection_params)# 在連接上創建 AMQP 信道self.channel = self.connection.channel()# 聲明節點專用隊列(綁定到該信道)# 如果隊列不存在則自動創建,如果存在則直接綁定self.channel.queue_declare(queue=self.NODE_NAME,   # 隊列名稱(使用節點名作為唯一標識)durable=True            # 隊列持久化標志,需要配合消息的delivery_mode=2使用才能完全持久化)# 控制并發數,值越大并發越高,但資源消耗和復雜度也增加# TODO 集群需要調研配置并發度self.channel.basic_qos(prefetch_count=1)# 將當前信道綁定到指定隊列,開始監聽消息,消費消息(通過該信道)self.channel.basic_consume(queue=self.NODE_NAME,   # 指定消費的隊列名稱(當前節點專屬隊列)on_message_callback=self._execute_command,  # 消息處理回調函數auto_ack=False          # 手動消息確認模式)def _execute_command(self, ch, method, props, body):"""執行接收到的命令并返回結果"""try:# 解析消息內容(JSON格式)message = json.loads(body.decode('utf-8'))command = message.get('command', '')    # 獲取要執行的命令target = message.get('target', '')      # 獲取目標節點標識logger.info(f" [x] 收到({target})命令:{command}")# 校驗目標節點(防止誤處理其他節點的消息)if target != self.NODE_NAME:logger.warning(f" [x] 收到非本節點({self.NODE_NAME})命令,已忽略")ch.basic_ack(delivery_tag=method.delivery_tag)  # 確認消息(防止重新投遞)returnlogger.info(f" [*] 執行命令 【{command}】...")try:# 通過子進程執行命令(同步阻塞)output = subprocess.check_output(command,shell=True,     # 啟用shell解析stderr=subprocess.STDOUT,   # 捕獲標準錯誤timeout=60      # 超時時間(秒))response = output.decode('utf-8')except subprocess.TimeoutExpired:# 超時異常response = "Error: Command timed out"except subprocess.CalledProcessError as e:# 命令執行失敗response = f"Error: {e.output.decode('utf-8')}"except Exception as e:# 其他系統異常response = f"System Error: {str(e)}"# 返回執行結果ch.basic_publish(exchange='',    # 默認交換器routing_key=props.reply_to, # 回復到客戶端指定的回調隊列properties=pika.BasicProperties(correlation_id=props.correlation_id,    # 關聯ID(匹配請求-響應)delivery_mode=2 # 持久化消息到磁盤,會降低性能(服務重啟不丟失)),body=response.encode('utf-8')   # 響應內容)logger.info(f" [*] 命令執行完成")# 確認消息處理完成ch.basic_ack(delivery_tag=method.delivery_tag)except Exception as e:# 全局異常處理logger.exception(f" [x] 消息處理異常: {str(e)}")# 否定確認(可能重新投遞)ch.basic_nack(delivery_tag=method.delivery_tag)def start(self, max_retries=5, retry_delay=10):"""啟動RabbitMQ服務并持續監聽消息功能:管理服務生命周期,處理連接異常和重試邏輯:param max_retries: 最大重試次數,默認5次:param retry_delay: 重試間隔時間(秒),默認10秒:return:"""# 當前重試次數計數器retry_count = 0# 主服務循環(持續運行直到主動終止)while True:try:# 打印服務狀態信息logger.info(f" [*] {self.NODE_NAME} 節點服務啟動 (嘗試 {retry_count + 1}/{max_retries})")logger.info(f" [*] 等待隊列 {self.NODE_NAME} 中的請求...")# 檢查并重建連接(如果不存在或已關閉)if not hasattr(self, 'connection') or self.connection.is_closed:self._setup_connection()    # 初始化AMQP連接# 開始消費消息(阻塞調用)self.channel.start_consuming()except pika.exceptions.AMQPConnectionError as e:# RabbitMQ連接異常處理retry_count += 1logger.exception(f"連接失敗: {str(e)}")# 超過最大重試次數則終止服務if retry_count >= max_retries:logger.error(" [x] 達到最大重試次數,終止服務")self.close()break   # 退出循環# 未達上限則延遲重試logger.warning(f" [*] {retry_delay}秒后嘗試重新連接...")time.sleep(retry_delay)except KeyboardInterrupt:# 處理用戶主動終止(Ctrl + C)logger.error("\n [x] 接收到終止信號")self.close()logger.error(" [x] 服務已停止")break   # 退出循環except Exception as e:# 其他未捕獲異常處理logger.exception(f"服務異常: {str(e)}")time.sleep(retry_delay) # 防止異常時CPU空轉def close(self):"""安全關閉RabbitMQ連接功能:清理資源,確保連接被正確關閉:return:"""# 防御式編程:檢查連接存在且未關閉if hasattr(self, 'connection') and not self.connection.is_closed:self.connection.close() # 關閉AMQP連接logger.info(" [x] 連接已安全關閉")if __name__ == '__main__':# 服務啟動入口(自動獲取主機名作為節點名)server = RabbitMQServer()try:server.start()except KeyboardInterrupt:logger.error("\n [x] 接收到終止信號")server.close()logger.error(" [x] 服務已停止")

2.客戶端

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@File:      rabbitmq_client.py
@Date:      2025/6/26 10:43
@Author:    xxx
@Description:
1. RabbitMQ客戶端類,支持向指定節點發送SSH命令
2. 作為控制端運行,可定向發送命令并接收執行結果
"""import ssl
import pika
import time
import uuid
import json
import socket
import logging
import configparser# 定義日志模塊
logger = logging.getLogger()
# 設置全局日志級別設為最低(DEBUG)
# # 可選: DEBUG, INFO, WARNING, ERROR, CRITICAL
logger.setLevel(logging.DEBUG)# 1. 文件日志(僅輸出到文件)
file_handler = logging.FileHandler('rabbitmq_client.log', encoding='utf-8')
file_handler.setLevel(logging.DEBUG)  # 文件記錄DEBUG及以上級別
file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(lineno)04d - %(message)s', datefmt="%Y-%m-%d %H:%M:%S"))
logger.addHandler(file_handler)# 2. 控制臺日志(僅輸出到控制臺)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)  # 控制臺僅顯示INFO及以上
console_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(lineno)04d - %(message)s', datefmt="%Y-%m-%d %H:%M:%S"))
logger.addHandler(console_handler)RABBITMQ_HOST_CONF = "/etc/rabbitmq/rabbitmq.conf"class RabbitMQClient:"""RabbitMQ RPC客戶端類功能:向指定節點發送命令并獲取執行結果"""def __init__(self, mq_user="rabbitmq", mq_password="rabbitmq@123", mq_virtual_host="/",mq_host=None, mq_port=5671, mq_ca="/opt/ssl/ca_certificate.pem"):"""初始化RabbitMQ客戶端:param mq_user: RabbitMQ用戶名:param mq_password: RabbitMQ密碼:param mq_virtual_host: 虛擬主機:param mq_host: RabbitMQ服務器IP:param mq_port: RabbitMQ服務端口:param mq_ca: SSL證書路徑"""# 連接配置self.RABBITMQ_USER = mq_userself.RABBITMQ_UNLOCK_CODE = mq_passwordself.RABBITMQ_VIRTUAL_HOST = mq_virtual_host# 如果沒有設置RabbitMQ服務器IP,則連接到配置文件中設置的IP節點self.RABBITMQ_HOST = mq_host if mq_host else self.get_option(RABBITMQ_HOST_CONF, "global", "rabbitmq_host")self.RABBITMQ_PORT = mq_portself.SSL_CA_PATH = mq_ca# 響應相關變量self.response = Noneself.corr_id = None# 建立連接logger.info(" [x] 正在建立連接 ...")self._connect()logger.info(" [x] 連接建立成功")def get_option(self, file_path, section, option):"""獲取 file_path 配置項值,若配置文件沒有,返回空字符串:param section: section字符串,例如:'global':param option: key值,例如:'manage_nodes':return: 字符串類型數據"""parser = configparser.ConfigParser()parser.read(file_path)if not parser.has_option(section, option):return ""else:return parser.get(section, option)def _connect(self):"""建立RabbitMQ連接并初始化回調隊列功能:配置安全連接參數、創建通信信道、設置消息回調處理:return:"""# 創建SSL安全上下文,強制使用TLS 1.2協議(禁用不安全的老版本協議)ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)# 加載CA根證書用于驗證服務端證書(防止中間人攻擊)ssl_context.load_verify_locations(self.SSL_CA_PATH)# 將SSL配置封裝為RabbitMQ專用的SSLOptions對象# "localhost"參數要求服務端證書必須包含該主機名(CN或SAN字段)ssl_options = pika.SSLOptions(ssl_context, "localhost")# 創建認證憑證對象(明文用戶名/密碼,實際傳輸時會通過SSL加密)credentials = pika.PlainCredentials(self.RABBITMQ_USER,         # RabbitMQ服務用戶名self.RABBITMQ_UNLOCK_CODE   # RabbitMQ服務密碼)# 配置連接參數connection_params = pika.ConnectionParameters(host=self.RABBITMQ_HOST,    # RabbitMQ服務器地址port=self.RABBITMQ_PORT,    # 默認使用5671加密端口virtual_host=self.RABBITMQ_VIRTUAL_HOST,    # 虛擬主機隔離環境credentials=credentials,    # 用戶名密碼憑證ssl_options=ssl_options,    # SSL安全配置heartbeat=60                # 1分鐘心跳檢測(防連接中斷),更頻繁的心跳檢測(如AWS ELB默認60秒空閑超時))# 建立阻塞式連接(同步操作,會阻塞直到連接成功或拋出異常)self.connection = pika.BlockingConnection(connection_params)# 創建AMQP信道(單個連接可創建多個信道,減少TCP連接開銷)self.channel = self.connection.channel()# 聲明臨時回調隊列(exclusive=True表示連接關閉時自動刪除隊列)result = self.channel.queue_declare(queue='',       # 空隊列名表示由RabbitMQ自動生成exclusive=True  # 獨占隊列,僅當前連接可用)# 保存自動生成的隊列名稱(用于接收服務端響應)self.callback_queue = result.method.queue# 綁定消息消費回調self.channel.basic_consume(queue=self.callback_queue,  # 監聽回調隊列on_message_callback=self._on_response,  # 響應消息處理函數# TODO 生產環境建議:auto_ack=False  改為手動ACK確保消息可靠處理auto_ack=False   # auto_ack=True 自動確認消息(不推薦生產環境使用))def _on_response(self, ch, method, props, body):"""RPC模式下的響應消息回調處理函數功能:匹配并接收服務端返回的命令執行結果處理邏輯:1.通過correlation_id匹配對應的請求2.將二進制消息體解碼為字符串3.存儲結果供execute_command方法獲取:param ch: (pika.channel.Channel): 接收到消息的信道對象:param method: (pika.spec.Basic.Deliver): 包含投遞信息(如delivery_tag):param props: (pika.spec.BasicProperties): 消息屬性(含correlation_id等):param body: (bytes): 消息體內容(服務端返回的執行結果):return:"""# 校驗消息關聯ID(確保是本請求的響應)try:if self.corr_id == props.correlation_id:# 解碼服務端返回的消息內容(UTF-8編碼)self.response = body.decode('utf-8')# 注意:此處不需要手動ack,因為消息已在服務端處理時ackexcept UnicodeDecodeError as e:self.response = f"解碼失敗: {str(e)}"def execute_command(self, command, target_node=None, timeout=60):"""向指定RabbitMQ節點發送命令并獲取執行結果(RPC模式):param command (str): 要執行的shell命令字符串(如"ls -l"):param target_node (str): 目標節點標識,對應服務端的隊列名- 默認None表示發送到當前主機節點:param timeout (int): 等待響應的超時時間(秒),默認60秒:return str: 命令執行結果文本異常:TimeoutError: 超過指定時間未收到響應時拋出AMQP相關異常: 消息發送失敗時拋出向指定節點執行遠程命令"""# 初始化響應存儲和請求IDself.response = None    # 清空之前的響應self.corr_id = str(uuid.uuid4())    # 生成唯一請求標識# 確定目標節點(如果執行命令沒有指定節點,默認發送到當前主機)if not target_node:target_node = socket.gethostname()# 構建RPC請求消息體(JSON格式)(包含命令和目標節點信息)message = {"command": command,         # 要執行的命令"target": target_node,      # 目標節點標識"timestamp": time.time()    # 請求時間戳}# 發送消息到目標節點的專屬隊列self.channel.basic_publish(exchange='',    # 使用默認直連交換機routing_key=target_node,  # 通過隊列名路由到指定節點properties=pika.BasicProperties(reply_to=self.callback_queue,   # 設置回調隊列名correlation_id=self.corr_id,    # 標記請求ID),# JSON序列化消息body=json.dumps(message).encode('utf-8'))# 等待響應(帶超時機制)start_time = time.time()while self.response is None:# 處理網絡事件(非阻塞)self.connection.process_data_events()# 超時檢查if time.time() - start_time > timeout:raise TimeoutError(f"等待節點 {target_node} 響應超時")# 避免CPU空轉,此處sleep不能太長,影響命令返回時效性time.sleep(0.1)return self.response    # 返回執行結果def close(self):"""安全關閉RabbitMQ連接功能:1. 清理網絡連接資源2. 自動刪除臨時隊列(exclusive隊列)3. 防止資源泄漏:return:"""if self.connection and not self.connection.is_closed:# 關閉連接(會觸發信道關閉)self.connection.close()logger.warning(" [x] 連接已關閉")if __name__ == '__main__':# 使用示例client = RabbitMQClient()try:# 向不同節點發送命令nodes = ["node247", "node248", "node249"]for node in nodes:try:logger.info(f"\n向節點 {node} 執行命令: hostname")logger.info(client.execute_command(command="hostname", target_node=node))except Exception as e:logger.exception(f"節點 {node} 執行失敗: {str(e)}")try:logger.info(f"\n向節點 {node} 執行命令: ls -l /opt/")logger.info(client.execute_command(command="ls -l /opt/", target_node=node))except Exception as e:logger.exception(f"節點 {node} 執行失敗: {str(e)}")try:logger.info(f"\n向節點 {node} 執行命令: date")logger.info(client.execute_command(command="date", target_node=node))except Exception as e:logger.exception(f"節點 {node} 執行失敗: {str(e)}")finally:client.close()

3.調用結果

# 服務端,節點啟動
192.168.120.17 node17
192.168.120.18 node18
192.168.120.19 node19python3 rabbitmq_server.py# 客戶端,節點啟動
192.168.120.17 node17python3 rabbitmq_client.py

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

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

相關文章

Rust代碼規范之蛇形命名法和駝峰命名法

Rust 使用兩種主要的命名風格:駝峰命名法(UpperCamelCase)和蛇形命名法(snake_case)。通常,類型(如結構體、枚舉、特征)使用駝峰命名法,而變量、函數、方法等使用蛇形命名…

編寫CSS的格式

1、內聯樣式的css import React, { PureComponent } from reactexport class App extends PureComponent {constructor() {super()this.state {fs: 20}}render() {const { fs } this.statereturn (<div><p style{{ color: red, fontSize: ${fs}px }}>哈哈哈哈哈…

Redis—主從復制

引言 Redis的應用還得是在分布式系統當中。在分布式系統中&#xff0c;涉及到一個非常關鍵的問題&#xff0c;就是單點問題。例如&#xff0c;如果某個服務器程序&#xff0c;只有一個節點&#xff08;只搞了一個物理服務器&#xff0c;來部署這個服務器程序&#xff09;&…

【網絡安全】從IP頭部看網絡通信:IPv4、IPv6與抓包工具 Wireshark 實戰

從IP頭部看網絡通信&#xff1a;IPv4、IPv6與抓包工具 Wireshark實戰 在網絡安全分析和數據通信的世界中&#xff0c;一切都始于“數據包”。數據包是網絡上傳輸的基本單位&#xff0c;而數據包的結構與內容&#xff0c;正是我們理解網絡行為的核心。本文將帶你深入了解 IP 協…

IPv4網絡地址分類

目錄 一、核心分類標準 二、詳細范圍與主機數量 1. A類網絡&#xff08;超大規模網絡&#xff09; 2. B類網絡&#xff08;中大型網絡&#xff09; 3. C類網絡&#xff08;小型網絡&#xff09; 三、三類網絡對比表 四、保留地址說明 五、現代網絡中的變化 六、主機數…

Qt:QCustomPlot庫簡介

QCustomPlot 是一個基于 Qt 框架的輕量級 C 繪圖庫&#xff0c;專為高效繪制二維圖表&#xff08;如曲線圖、柱狀圖、金融圖表等&#xff09;而設計。相比 Qt Charts 模塊&#xff0c;它以 高性能 和 高度可定制性 著稱&#xff0c;尤其適合需要實時數據可視化的科學計算、工業…

【云桌面容器KasmVNC】如何關閉SSL使用HTTP

1 緣起 根據實際的訴求,調整實現方式。 為用戶提供云瀏覽器(通過瀏覽器訪問遠程瀏覽器),多用戶的每個任務提供資源隔離的云瀏覽器。 該功能,由同事祥嵩曾調研與開發,使用KasmVNC實現功能,非常佩服祥嵩,無論是技術廣度還是技術深度都是杠杠滴,無可挑剔。 實際的訴求是…

跟著AI學習C#之項目實戰-電商平臺 Day5

&#x1f4c5; Day 5&#xff1a;訂單提交與支付模擬 ? 今日目標&#xff1a; 創建 Order 和 OrderItem 模型實現從購物車生成訂單的功能模擬支付流程&#xff08;成功/失敗頁面&#xff09;添加訂單狀態跟蹤&#xff08;如“待付款”、“已發貨”等&#xff09;提交 Git 版…

復雜驅動開發-TLE9471的休眠流程與定時喚醒

文章目錄 前言休眠流程定時喚醒功能總結 前言 開發SBC時非常重要的一環就是開發休眠流程&#xff0c;其目的是為了保證接KL30的ECU在休眠模式下盡可能小的消耗低壓蓄電池的電量&#xff0c;防止車輛放置長時間后出現虧電。而定時喚醒功能在部分ECU中會有需求休眠后定期對車輛狀…

Spark 之 Reuse

src/main/scala/org/apache/spark/sql/execution/reuse/ReuseExchangeAndSubquery.scala case object ReuseExchangeAndSubquery extends Rule[SparkPlan] {def apply(plan: SparkPlan): SparkPlan = {if (conf.exchan

Solidity學習 - 錯誤處理

文章目錄 前言EVM錯誤處理機制EVM錯誤處理的核心特性程序中的錯誤處理 錯誤拋出方法require()函數require()觸發異常的場景關鍵特性 assert()函數assert()觸發異常的場景關鍵特性 require() vs assert()&#xff1a;選擇指南revert()函數關鍵特性 異常捕獲&#xff1a;try/catc…

如何永久刪除Android上的短信[無法恢復]

當您不再保留 Android 設備時&#xff0c;您將需要徹底刪除所有私人數據&#xff0c;包括短信。因此&#xff0c;有必要了解如何永久刪除Android上的短信。現在&#xff0c;閱讀本指南&#xff0c;掌握消除信息的實用方法。 第 1 部分&#xff1a;如何一鍵永久刪除 Android 上的…

P12894 [藍橋杯 2025 國 Java B] 智能交通信號燈

[Problem] \color{blue}{\texttt{[Problem]}} [Problem] 給定一個長度為 n n n 的數組 a 1 … n a_{1\dots n} a1…n?&#xff0c;進行 m m m 次一下操作&#xff1a; 給定 l , r l,r l,r&#xff0c;求出 ∑ l ≤ i < j ≤ r mex { a i , a j } \sum\limits_{l \le…

華為云Flexus+DeepSeek征文|基于華為云一鍵部署的 Dify-LLM 平臺構建智能試卷生成助手

目錄 前言 1 華為云Dify-LLM應用平臺部署 1.1 一鍵部署平臺簡介 1.2 四步完成部署流程 2 接入華為云 DeepSeek 自定義大模型 2.1 ModelArts Studio 模型服務介紹 2.2 配置自定義大模型 3 創建試卷生成工具&#xff08;工作流&#xff09; 3.1 設計 DSL 工作流 3.2 工…

嵌入式硬件與應用篇---寄存器GPIO控制

在 ARM 架構中&#xff0c;通過 32 位寄存器控制 GPIO&#xff08;通用輸入輸出&#xff09;的核心步驟和方法可分為以下幾個關鍵環節&#xff0c;結合不同芯片的實現差異&#xff0c;具體操作需參考對應的數據手冊&#xff1a; 一、GPIO 控制的核心步驟 1. 使能 GPIO 時鐘 …

Fiddler中文版抓包工具在跨域與OAuth調試中的深度應用

跨域和OAuth授權流程一直是Web和移動開發中最容易踩坑的領域。復雜的CORS配置、重定向中的Token傳遞、授權碼流程的跳轉&#xff0c;以及多域名環境下的Cookie共享&#xff0c;常常讓開發者陷入調試困境。此時&#xff0c;一款能夠精準捕獲、修改、重放請求的抓包工具顯得至關重…

React用戶交互事件

在React中處理用戶交互事件&#xff08;如點擊、輸入、提交等&#xff09;的方式與原生JavaScript類似&#xff0c;但有一些語法差異和最佳實踐。以下是常見交互事件的處理方法及代碼示例&#xff1a; 一、基本事件處理&#xff08;點擊、輸入等&#xff09; 1. 點擊事件&…

DHT11 STM32 HAL驅動庫 整數

dht11.h #ifndef __DHT11_H #define __DHT11_H#include "stm32f1xx_hal.h" // 根據實際芯片型號調整&#xff08;如stm32f4xx_hal.h&#xff09;// DHT11數據結構 typedef struct {GPIO_TypeDef *GPIOx; // GPIO端口&#xff08;如GPIOA&#xff09;uint16_t GP…

【Actix Web 精要】Rust Web 服務開發核心技術與實戰指南

目錄 一、Actix Web 核心架構解析1.1 核心組件交互流程1.2 關鍵組件說明&#xff1a; 二、項目初始化與配置2.1 創建項目2.2 添加依賴 (Cargo.toml)2.3 項目結構 三、核心模塊實現3.1 配置管理 (src/config.rs)3.2 應用狀態管理 (src/main.rs)3.3 數據模型 (src/models/user.rs…

從URL到視頻:用Python和AI構建自動化內容講解視頻生成管道

摘要 本文旨在從技術層面&#xff0c;深入探討并實踐一個將任意網頁鏈接&#xff08;如飛書文檔、博客文章&#xff09;自動轉換為帶有配音和字幕的講解視頻的系統。我們將詳細拆解整個實現流程&#xff0c;覆蓋從內容抓取與解析、利用大語言模型&#xff08;LLM&#xff09;智…