施磊老師rpc(一)

文章目錄

  • mprpc項目
    • **項目概述**:
    • 深入學習到什么
    • **前置學習建議**:
    • 核心內容
    • 其他技術與工具
    • **項目特點與要求**:
    • **環境準備**:
  • 技術棧
  • 集群和分布式理論
    • 單機聊天服務器案例分析
    • 集群聊天服務器分析
    • 分布式系統介紹
    • 多個模塊的局限
    • 引入分布式 RPC 通信框架的意義
    • 三大形態對比--**重點**
  • RPC 通信原理講解整理
    • 為什么要使用 RPC?
    • RPC 通信的完整過程(調用鏈)
    • 關鍵模塊說明(圖中重要角色)
    • 返回結果的組成與處理
    • 框架的作用與實現目標
    • 舉例鞏固(Login 方法調用)
    • protobuf優點
    • 總結
  • 環境配置
    • 類似于集群項目
    • protobuf
  • protobuf使用(一)
    • 安裝vscode插件
    • 簡單使用
    • 代碼
    • protoc編譯
    • 序列化和反序列化使用
    • 編譯注意
  • protobuf使用(二)
    • string和**bytes**
      • `bytes` 類型的作用:
      • 與 `string` 的區別:
      • 注意事項
    • protobuf的枚舉
    • repeated(重復)
    • repeated常用方法(C++)
    • message嵌套message
    • mutable_字段--**重點**
    • add_成員和()
    • main使用
    • 重要的是-學會看**.h**里面的函數

mprpc項目

分布式 網絡通信 框架

基于muduo+protobuf

業界優秀的RPC框架:baidu的brpc,google的grpc

項目概述

本課程將使用 C/C++ 編寫分布式網絡通信框架項目,重點講解從單機服務器到集群服務器,再到項目模塊化分解與分布式部署的過程。

深入學習到什么

希望 可以 對 單機----集群-----分布式 有更好的理解

前置學習建議

學習本項目前,建議先完成 C/C++ 項目集群的網絡聊天通信項目,以便更好地理解服務器集群概念及其優勢,為學習分布式知識打下基礎。

技術選型

  • 網絡庫:采用 muduo 高性能網絡庫(底層基于 I/O 線程池模型) 。
  • 序列化 / 反序列化:使用 protobuf 處理數據序列化和反序列化,以及遠程調用方法的識別、參數處理。
  • 命名:基于 muduo 庫和 protobuf 首字母,將項目命名為 mprpc。

核心內容

  • 講解集群與分布式的概念及原理。
  • 剖析 rpc 遠程過程調用的原理與實現。
  • 闡述服務注冊中心(如 ZooKeeper)在分布式環境中的作用。

其他技術與工具

  • 涉及 C++11 和 C++14 的新語法(如線程級別的本地變量、綁定器與函數對象等)。
  • 使用 VS Code 進行跨平臺開發,在 Linux 環境下遠程開發項目。
  • 介紹 muduo 庫網絡編程、conf 配置文件讀取、cmake 構建集成編譯環境及 GitHub 項目托管。

項目特點與要求

項目代碼量雖比集群聊天項目少,但對技術棧的理解深度和廣度要求更高,更注重對集群和分布式的理解 。

環境準備

開發前需掌握 Linux 環境下 muduo 網絡庫(依賴 boost 庫)的安裝,相關安裝步驟可參考博主博客,且 muduo 庫網絡編程示例、cmake 構建編譯環境在集群聊天服務器項目中已詳細講解。

技術棧

  1. 集群和分布式概念以及原理
  2. RPC遠程過程調用原理以及實現
  3. Protobuf數據序列化和反序列化協議
  4. ZooKeeper分布式一致性協調服務應用以及編程
  5. muduo網絡庫編程
  6. conf配置文件讀取
  7. 異步日志
  8. CMake構建項目集成編譯環境
  9. github管理項目

代碼沒有集群多, 但是 知識更深入

集群和分布式理論

單機聊天服務器案例分析

服務器模塊與業務:以單機聊天服務器為例,其包含用戶管理、好友管理、群組管理、消息管理和后臺管理五個模塊。每個模塊對應多項特定業務,如用戶管理包括登錄、注冊、注銷;好友管理涉及添加、刪除好友等,這些業務由一個或多個相關函數實現。

性能與設計瓶頸:

  • 硬件資源限制單機服務器受硬件資源制約,例如 32 位 Linux 系統的聊天服務器,進程資源耗盡時,最多僅能支持約兩萬用戶同時在線,難以承載更多客戶端連接與服務。
  • 運維與代碼編譯成本高:由于模塊都在同一項目運行單元,任意模塊的修改(哪怕只是一行代碼),都需重新編譯整個項目代碼(耗時約 2 小時),并重新部署(耗時約 3 小時),成本巨大。
  • 硬件資源分配不合理:不同模塊對硬件資源需求不同,存在 CPU 密集型和 IO 密集型模塊。但單機服務器只能采用平衡方案部署,無法針對各模塊需求進行硬件資源的精準匹配。

集群聊天服務器分析

性能提升:通過水平擴展硬件資源,增加服務器數量(如三臺或更多),每臺獨立運行聊天服務器程序,解決了單機服務器受硬件資源限制導致的用戶并發量低的問題。

存在問題

  • 編譯成本高:各服務器上的模塊仍在同一項目中部署,運行于一個服務進程,因此任意模塊修改仍需整體重新編譯代碼,且需多次部署到不同服務器,運維成本更高
  • 硬件資源分配不合理:集群只是簡單擴展機器,無法針對不同模塊(CPU 密集型或 IO 密集型)的硬件資源需求進行精準部署,存在資源浪費。例如后臺管理模塊并發需求低,卻隨整體系統在多臺服務器部署 。

其他特點應用:集群部署方式簡單,在高并發突發場景(如雙 11)能快速通過增加服務器和負載均衡器提升服務能力

在集群中機器數量與性能并非成正比,原因如下:

  • 通信成本:機器增多使節點間通信開銷增大,占用帶寬與處理時間,易引發網絡擁塞。
  • 分配難題:數據和任務難以在更多機器上均勻分配,易造成資源浪費。
  • 復雜故障:系統復雜度隨機器數上升,故障和配置問題更易影響性能。
  • 并行局限:部分任務不適合大規模并行或并行度有限,加機器也無法提升性能。

以下任務不適合大規模集群并行處理:

  • 順序依賴型:步驟間嚴格先后關聯,無法拆分并行,如按序的數據清洗與分析。
  • 高通信成本型:執行中需頻繁大量數據交互,易受網絡帶寬制約,如高頻金融交易數據處理。
  • 任務粒度過小:任務簡單微小,集群調度、協調開銷超執行時間,如大量小文件簡單格式轉換。

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

分布式系統介紹

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

定義與特點:將一個工程拆分為多個模塊,每個模塊獨立部署為可運行的服務進程,多臺服務器(分布式節點)協同工作構成完整系統。與集群區別在于,集群中每臺服務器運行完整系統,而分布式是多臺服務器共同組成一個系統 。

解決的問題

  • 并發與資源優化:可根據分布式節點的并發需求靈活擴容,如對用戶管理模塊所在節點增加服務器以支持更高并發,同時合理利用其他節點空閑資源,提升資源利用率。
  • 編譯與部署優化模塊獨立部署,單個模塊修改僅需重新編譯和更新該模塊,無需影響其他模塊,大大降低編譯和部署成本。
  • 硬件匹配優化:模塊拆分后,可依據各模塊特性(CPU 密集型或 IO 密集型)精準匹配硬件資源,實現資源的合理配置。

潛在問題與應對:分布式系統中部分節點故障可能影響整體服務,但實際生產中可通過配置主備服務器等容災方案保障高可用性 。

多個模塊的局限

模塊劃分困難

  • 模塊之間的邊界不清晰,容易出現功能重疊或代碼重復。
  • 模塊耦合度高,修改難、維護難。
  • 若劃分不當,容易造成大量重復代碼、邏輯冗余、維護成本高。

模塊之間的通信復雜–重點

  • 分布式部署后,模塊間通信需跨進程、跨機器
  • 函數調用從本地調用變為遠程調用,需涉及:
    • 函數名、參數傳輸
    • 網絡通信、序列化/反序列化
    • 異常處理、響應返回等機制

引入分布式 RPC 通信框架的意義

核心作用

讓“跨主機遠程調用函數”像“調用本地函數”一樣簡單透明

解決的核心問題

  1. 統一通信流程,屏蔽底層復雜性
    • 請求封裝 + 網絡傳輸 + 響應處理全部自動完成。
  2. 提高模塊間調用效率與開發體驗
    • 用戶感知不到遠程調用的差異,只需像本地函數一樣使用接口。
  3. 支持參數序列化與傳輸
    • 使用 Protobuf 進行高效的數據結構序列化。
  4. 自動服務發現與定位
    • 通過 ZooKeeper 注冊中心查找服務位置,實現動態服務綁定。

三大形態對比–重點

系統形態特點優勢局限性
單機服務器所有模塊在一個進程開發簡單擴展性差、耦合高
集群服務器多臺相同服務器水平擴展、簡單粗暴不是線性擴展、資源浪費
分布式模塊化系統各模塊獨立部署高可維護性、易擴展、低耦合設計復雜、通信困難(需RPC)

RPC 通信原理講解整理

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

為什么要使用 RPC?

  1. 為了解耦與擴展:
    • 大型系統按需模塊化(不同模塊對硬件/并發等要求不同),分布式部署成為必然。
    • 模塊分布在不同進程、甚至不同機器上,相互之間仍需調用方法 —— 就必須跨進程/跨機器通信
  2. 屏蔽底層通信細節:
    • 本質是“遠程函數調用”,但不同于本地函數調用的直接跳轉和傳參。
    • 不希望每個開發者都去手動處理 socket、序列化、反序列化、錯誤碼等細節。
    • 引入“框架”來自動完成這些通信細節,開發者只專注于業務邏輯即可。

RPC 通信的完整過程(調用鏈)

舉例:用戶模塊調用好友模塊的 getUserFriendList(userId) 方法(模塊部署在不同服務器)

Caller(調用方)          →         Stub(客戶端代理)          →         網絡層↓                                          ↓                                     ↓發起調用(方法名+參數) → 序列化(打包)         → 網絡發送↑                                          ↑                                     ↑接收返回(結果/錯誤) ← 反序列化(解包) ← 網絡接收
步驟說明
1. 調用方發起函數調用比如:getUserFriendList(userId),但這個方法實際存在于另一臺機器。
2. Stub 代理類攔截調用替你處理所有 RPC 通信細節。
3. 參數序列化(打包)方法名、參數 → 序列化成字節流(如 JSON、Protobuf)
4. 網絡傳輸使用網絡庫(如 muduo)將字節流發送到目標服務器
5. 服務端接收網絡層接收到請求后交給服務端的 Stub 處理
6. 參數反序列化字節流 → 方法名 + 參數
7. 執行遠程函數找到目標函數(如 getUserFriendList),執行邏輯處理
8. 返回結果處理執行結果、錯誤碼、錯誤信息 → 序列化返回
9. 調用方接收響應解包結果 → 返回給應用層,像本地函數一樣使用返回值

關鍵模塊說明(圖中重要角色)

角色功能簡述
Caller發起方(如用戶模塊),調用遠端方法
Stub(客戶端樁)代理模塊,封裝參數、處理序列化、發送請求等
網絡層通信基礎設施(如 muduo 庫),負責字節流的收發
Stub(服務端樁)接收數據并反序列化,請求轉發到本地業務模塊
Callee被調方(如好友模塊),真正執行業務方法
結果返回路徑與調用路徑對稱,同樣涉及打包、網絡傳輸和反序列化

返回結果的組成與處理

  • 返回值通常包括:
    1. 錯誤碼(errorCode)
    2. 錯誤信息(errorMessage)
    3. 業務數據(result)
  • 如果錯誤碼為非零,說明遠程執行出錯,不應使用返回值,僅使用錯誤信息

框架的作用與實現目標

  1. 由框架來完成:
    • 參數/返回值的序列化與反序列化
    • 方法名的標識與分發
    • 網絡通信(請求發送/接收)
    • 錯誤處理與返回機制
  2. 開發者只需寫業務邏輯函數,像調用本地函數一樣調用遠程服務

舉例鞏固(Login 方法調用)

  • 示例函數:login(string name, string password)
  • 發起調用:login("zhangsan", "123456")
  • 步驟:
    • Stub 序列化請求(函數名 + 參數)
    • 網絡發送請求
    • 遠端反序列化 + 調用 login()
    • 執行返回 true/false + 錯誤碼 + 信息
    • 遠端再次序列化發送
    • 調用方反序列化,判斷錯誤碼再處理返回值

protobuf優點

高效的序列化性能

  • 體積小:二進制格式,比 JSON、XML 更精簡,節省網絡帶寬。
  • 速度快:序列化和反序列化速度遠快于 JSON/XML,適合高頻數據傳輸場景。
  • 示例:1000 條用戶消息用 JSON 可能幾百 KB,而 Protobuf 僅幾十 KB。

跨語言支持

  • 支持多種語言自動生成代碼(C++、Java、Python、Go 等)。
  • 不同平臺、語言之間通信無需手寫解析邏輯,提高開發效率。
  • 示例:后端使用 C++,前端用 JavaScript,通過 proto 文件即可對接。

總結

  • RPC 的目標:讓遠程調用就像本地函數調用一樣簡單
  • 框架解決的是“通信”本質問題,而不是業務邏輯問題
  • 圖中的每一步都需要代碼支持,RPC 框架的核心就是實現這些自動化處理

zookeeper服務配置中心(專門做服務發現)

環境配置

類似于集群項目

protobuf

github 進行下載安裝 https://github.com/protocolbuffers/protobuf

一定要 下載 包里面 有 autogen.sh 的版本

沒有的 就是 高版本, bazel 和 cmake 都不好用, bug特別多!!

折騰了 半天, 高版本 一個是 安裝步驟變了, 一個是 bug一堆!!

不要安裝 21 版本之上, 一堆bug, 就裝 21版本及以下

sudo apt-get update
sudo apt-get install autoconf automake libtool curl make g++ unzip
git clone 下來
./autogen.sh
./configure
make && sudo make install
sudo ldconfig

protobuf使用(一)

內容并不多, 后續 從實踐中 學習

安裝vscode插件

vscode-proto3

簡單使用

Protobuf 中,package 后面跟的就是 包名,表示該 .proto 文件中定義的所有消息、服務、枚舉等都屬于這個“命名空間”,稱為 包名

包名是你自己定義的一個標識符,用來給這組 protobuf 定義加上“命名空間”。

代碼

test/protobuf/test.proto------proto 配置文件

syntax = "proto3"; //聲明protobuf的版本package hzhpro; // 聲明代碼所在的包(例如c++就是namespace)// 定義登錄請求消息類型 name pwd
message LoginRequest
{string name = 1;string pwd = 2;
}// 定義登錄響應消息類型
message LoginResponse
{int32 errcode = 1;string errmsg = 2;bool success = 3;
}

protoc編譯

–cpp_out=OUT_DIR Generate C++ header and source.

protoc test.proto --cpp_out=./

生成

test.pb.cc  test.pb.h

messgae 相當于 class類, 里面的 相當于 成員變量

序列化和反序列化使用

test/protobuf/main.cc

#include "test.pb.h"
#include <iostream>
#include <string>
using namespace hzhpro;  // 實際開發 要少用命名空間int main()
{// 封裝了login請求對象的數據LoginRequest req;req.set_name("zhang san");req.set_pwd("123123");// 對象數據序列化=>char*std::string send_buf;   if(req.SerializeToString(&send_buf)){std::cout<< send_buf.c_str()<<std::endl;}// 從send_buf反序列化LoginRequest reqB;if(reqB.ParseFromString(send_buf)){std::cout<<reqB.name()<<std::endl;std::cout<<reqB.pwd()<<std::endl;}return 0;
}

編譯注意

必須加 pthread-----因為 Protobuf 內部使用了線程相關的功能(如 std::thread, pthread_create

g++ main.cc test.pb.cc -lprotobuf -pthread

protobuf使用(二)

string和bytes

在 Protobuf 中,bytes 是一種字段類型,表示原始二進制數據,用途非常廣泛。

bytes 類型的作用:

它可以用來存儲:

  • 二進制數據(圖片、文件內容、壓縮數據)
  • 自定義序列化的結構體
  • 加密密鑰、哈希值
  • 或者就是一個 UTF-8 編碼的字符串(但不推薦當字符串來用)

string 的區別:

類型內容編碼是否可包含 \0推薦用途
stringUTF-8? 不可包含正常文本(人讀的)
bytes原始數據? 可以包含任意二進制數據

注意事項

  • 使用 bytes 時不能用 set_content("str") 來設置包含 \0 的數據,否則會截斷。
  • 應使用 set_content(const void* data, size_t size)

protobuf的枚舉

.proto 中每個枚舉成員 必須指定數值(不自動遞增)。

必須用分號 ; 結束每一行,這和 C++ 是不同的。

枚舉成員名建議用 全大寫字母,符合 protobuf 的命名習慣。

repeated(重復)

repeated 類型 字段名 = 編號;
message FriendList {repeated string friends = 1;
}

下面這個是 基本類型

FriendList list;
list.add_friends("Tom");
list.add_friends("Jerry");for (int i = 0; i < list.friends_size(); ++i) {std::cout << list.friends(i) << std::endl;
}

repeated常用方法(C++)

  • add_字段()?????→ 添加一個元素
  • 字段_size()???? → 獲取數量
  • 字段(index)????→ 獲取第 index 個元素(從 0 開始)
  • mutable_字段()??→ 獲取可修改的容器(高級操作)

message嵌套message

test/protobuf/test.proto

syntax = "proto3"; //聲明protobuf的版本package hzhpro; // 聲明代碼所在的包(例如c++就是namespace)message ResultCode
{int32 errcode = 1;bytes errmsg = 2;
}// 定義登錄請求消息類型 name pwd
message LoginRequest
{bytes name = 1;bytes pwd = 2;
}// 定義登錄響應消息類型
message LoginResponse
{ResultCode result = 1;// int32 errcode = 1;// bytes errmsg = 2;bool success = 3;
}message GetFriendListsRequest
{uint32 userid = 1;  // 獲取誰的請求
}message User
{bytes name =1;uint32 age = 2;enum  Sex  // 枚舉寫法注意{MAN=0;WOMAN=1;}Sex sex=3;
}message GetFriendResponse
{// int32 errcode = 1;  // 代碼重復// bytes errmsg = 2;ResultCode result = 1;repeated User friend_list=2; // 定義了一個列表類型,  這個_list沒啥特殊意義
}

重新編譯, 注意 vscode 緩存, 容易沒反應, 重新拉一下 頭文件

mutable_字段–重點

通過查找 pb.h 的 result 函數 ===== 這個result 就是 那個ResultCode 類對象

result 返回 const 引用, 不能修改值

mutable_result 返回指針, 可以修改值

const ::hzhpro::ResultCode& result() const;
::hzhpro::ResultCode* mutable_result();
void set_allocated_result(::hzhpro::ResultCode* result);
函數名返回類型用途
result()const ResultCode&只讀訪問
mutable_result()ResultCode*可寫訪問
set_allocated_result(ResultCode*)void設置已存在對象的所有權(高級用法)

add_成員和()

::hzhpro::User* add_friend_list();
const ::hzhpro::User& friend_list(int index) const;   //查看第幾個,  index 根據上面 

main使用

LoginResponse rsp;
ResultCode *rc = rsp.mutable_result();
rc->set_errcode(1);
rc->set_errmsg("登錄處理失敗");

自定義類型的 add_

int main()
{// LoginResponse rsp;// ResultCode *rc = rsp.mutable_result();// rc->set_errcode(1);// rc->set_errmsg("登錄處理失敗");GetFriendListsResponse rsp;ResultCode *rc = rsp.mutable_result();rc->set_errcode(0);User *user1 = rsp.add_friend_list();user1->set_name("zhang san");user1->set_age(26);user1->set_sex(User::MAN);User *user2 = rsp.add_friend_list();user2->set_name("zhang san-2");user2->set_age(26);user2->set_sex(User::MAN);User *user3 = rsp.add_friend_list();user3->set_name("zhang san-3");user3->set_age(26);user3->set_sex(User::WOMAN);std::cout<<rsp.friend_list_size()<<std::endl;User user = rsp.friend_list(2);std::string userstr;if(user.SerializeToString(&userstr)){// std::cout<<userstr.c_str()<<std::endl;// 這個有問題, 序列化后是二進制數據流, 本身是 字符串能打印出來, 要是有別的 類型, 就不好說了}User userB;if(userB.ParseFromString(userstr)){std::cout<<userB.name()<<std::endl;std::cout<<userB.age()<<std::endl;std::cout<<userB.sex()<<std::endl;}return 0;
}
3
zhang san-3
26
1

重要的是-學會看**.h**里面的函數

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

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

相關文章

基于LangChain構建最小智能體(Agent)實現指南

摘要 本文完整解析基于LangChain的極簡Agent實現方案&#xff0c;通過26行代碼構建具備網絡搜索能力的對話系統&#xff0c;涵蓋Agent初始化、工具集成、流式回調等核心技術要點。適用于LLM應用開發者快速入門Agent開發。(參考項目代碼&#xff1a;Minimal Agent) 系統架構設計…

AWTK:一鍵切換皮膚,打造個性化UI

想讓你的應用在不同場景下都能完美呈現嗎&#xff1f;皮膚切換功能必不可少&#xff01;本文將介紹AWTK&#xff0c;一款強大的GUI框架&#xff0c;它通過內置資源管理和優化緩存&#xff0c;輕松實現皮膚切換功能。 前言 當今的UI應用中&#xff0c;為了滿足不同使用場景和…

【Vagrant+VirtualBox創建自動化虛擬環境】Ansible測試Playbook

文章目錄 Vagrant安裝vagrant安裝 VirtualBox如何使用 Ansible安裝AnsiblePlaybook測試創建hosts文件創建setup.yml文件 Vagrant Vagrant是一個基于Ruby的工具&#xff0c;用于創建和部署虛擬化開發環境。它使用Oracle的開源VirtualBox虛擬化系統&#xff0c;使用 Chef創建自動…

AI在醫療領域的10大應用:從疾病預測到手術機器人

AI在醫療領域的10大應用&#xff1a;從疾病預測到手術機器人 系統化學習人工智能網站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目錄 AI在醫療領域的10大應用&#xff1a;從疾病預測到手術機器人摘要引言1. 醫學影像診斷&#xff1a;從靜態…

Win11 配置 Git 綁定 Github 賬號的方法與問題匯總

目錄 一、創建 Github 項目庫&#xff08;遠程倉庫&#xff09;二、配置安裝好的 Git1. 設置用戶信息2. 查看已配置的信息3. 建立本地倉庫4. Git 的常用命令1&#xff09;git checkout&#xff08;切換&#xff09;2&#xff09;git push&#xff08;上傳&#xff09;3&#xf…

6.應用層

6. 應用層 1. 概述 應用層是計算機網絡體系結構的最頂層&#xff0c;是設計和建立計算機網絡的最終目的&#xff0c;也是計算機網絡中發展最快的部分 早期基于文本的應用&#xff08;電子郵件、遠程登錄、文件傳輸、新聞組&#xff09;20世紀90年代將因特網帶入千家萬戶的萬維…

FPGA 100G UDP純邏輯協議棧

隨著器件等級的升高&#xff0c;高速serdes的線速率也隨之提高&#xff0c;RFSOC 4x最大可支持100G&#xff0c;主流方案為RDMA方案&#xff0c;該方案相對比較復雜&#xff0c;除了需要負責邏輯端的開發&#xff0c;還需操作系統中開發RDMA的驅動&#xff0c;對于對丟包不那么…

CSS實現DIV水平與垂直居中方法總結

大家好&#xff0c;歡迎來到程序視點&#xff01;我是你們的老朋友.小二&#xff01; CSS實現DIV水平與垂直居中方法總結 一、水平居中方案 標準方法 .center-div {margin-left: auto;margin-right: auto; }關鍵點&#xff1a;必須聲明DOCTYPE&#xff08;推薦XHTML 1.0 Tran…

Qt快速上手:QSettings高效配置讀寫實戰指南

文章目錄 前言一、QSettings初識&#xff1a;配置管理利器二、基礎操作三板斧2.1 文件讀寫基礎2.2 數據類型處理指南2.3 分組管理技巧 三、高級技巧&#xff1a;精準控制配置項3.1 監聽配置變更3.2 批量操作配置項 四、避坑指南&#xff1a;那些你可能會遇到的問題4.1 鍵順序重…

2025運維工程師面試題1(答案在后一張)

一、邏輯思維能力考核&#xff1a; 問題1&#xff1a; 3個人去投宿&#xff0c;一晚30元三個人每人掏了10元湊夠30元交給了老板后來老板說今天優惠只要25元就夠了&#xff0c;拿出5元命令服務生退還給他們&#xff0c;服務生偷偷藏起了2元&#xff0c;然后&#xff0c;把剩下…

react中封裝一個預覽.doc和.docx文件的組件

主要用到了mammoth這個插件,mammoth.js?是一個JavaScript庫&#xff0c;主要用于將Microsoft Word文檔&#xff08;.docx格式&#xff09;轉換為HTML。它可以通過Node.js環境使用&#xff0c;也可以直接在瀏覽器中使用。 關鍵代碼: import mammoth from mammoth; import { u…

c#WebsocketSever

這是一個winFrom的小工具&#xff0c;用于再本機創建一個c#服務的項目。 1、將本機ip地址改為左上角Ip&#xff0c;注意沒有“&#xff1a;”后的部分&#xff0c;那是端口號。 2、點擊中間按鈕&#xff0c;啟動服務器 3、如果啟動成功&#xff0c;會在下面顯示啟動成功&…

頂會招牌idea:機器學習+組合優化 優秀論文合集

2025深度學習發論文&模型漲點之——機器學習組合優化 機器學習&#xff08;ML&#xff09;與組合優化&#xff08;CO&#xff09;的交叉研究已成為運籌學與人工智能領域的前沿方向。傳統組合優化方法&#xff08;如分支定界、動態規劃&#xff09;雖在理論上有嚴格的性能保…

服務器硬件老化導致性能下降的排查與優化

隨著企業數字化轉型的深入&#xff0c;服務器作為IT基礎設施的核心載體&#xff0c;其穩定性與性能直接影響業務連續性。然而&#xff0c;硬件老化導致的性能衰減問題普遍存在且易被忽視。本報告通過系統性分析服務器硬件老化現象&#xff0c;提出多維度排查方法與優化方案&…

刪除k8s某命名空間,一直卡住了怎么辦?

以 kubectl delete ns cert-manager 命令卡住為例&#xff0c;并且命名空間一直處于 Terminating 狀態&#xff0c;說明 Kubernetes 無法完成刪除操作&#xff0c;通常是因為 Finalizers 阻塞或某些資源無法正常清理。 解決方法 1. 檢查命名空間狀態 kubectl get ns cert-man…

【分享】變聲器大師[特殊字符]喬碧蘿同款變聲[特殊字符]游戲變聲[特殊字符]

多種變聲器效果可選&#xff1a;爺爺、大叔、小孩、機器人...... 使用變聲器時只需輕輕一點&#xff0c;讓你成為潮人 【應用名稱】&#xff1a;變聲器大師 【應用版本】&#xff1a;6.1.35 【應用大小】&#xff1a;116M 【測試機型】&#xff1a;小米14 【下載鏈接】:https:…

【Part 2安卓原生360°VR播放器開發實戰】第二節|基于等距圓柱投影方式實現全景視頻渲染

《VR 360全景視頻開發》專欄 將帶你深入探索從全景視頻制作到Unity眼鏡端應用開發的全流程技術。專欄內容涵蓋安卓原生VR播放器開發、Unity VR視頻渲染與手勢交互、360全景視頻制作與優化&#xff0c;以及高分辨率視頻性能優化等實戰技巧。 &#x1f4dd; 希望通過這個專欄&am…

【JavaScript】相等運算符、條件運算符

1、相等運算符 &#xff08;1&#xff09;&#xff08;相等&#xff09; 相等運算符用來比較兩個值是否相等&#xff0c;如果相等會返回true&#xff0c;否則返回false <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"…

OceanBase數據庫-學習筆記5-用戶

用戶相關命令 命令描述CREATE USER ‘username’‘host’ IDENTIFIED BY ‘password’;創建用戶。GRANT ALL PRIVILEGES ON database_name.* TO ‘test_user’‘%’;給用戶授權所有權限。GRANT SELECT, INSERT, UPDATE ON database_name.* TO ‘test_user’‘%’;給用戶授權指…

K8S Secret 快速開始

一、什么是 Secret&#xff1f; Kubernetes&#xff08;K8s&#xff09;中的 Secret 是一種用于存儲和管理敏感信息&#xff08;如密碼、令牌、證書、API 密鑰等&#xff09;的資源對象。它避免了將敏感數據明文寫入配置文件、鏡像或代碼中&#xff0c;提供了一種更安全的方式…