【Json-Rpc #1】項目背景及環境搭建

在這里插入圖片描述

📃個人主頁:island1314

🔥個人博客:island

?? 歡迎關注:👍點贊 👂🏽留言 😍收藏 💞 💞 💞

  • 生活總是不會一帆風順,前進的道路也不會永遠一馬平川,如何面對挫折影響人生走向 – 《人民日報》

🔥 目錄

    • 一、項目介紹
    • 二、技術選型
      • 2.1 RPC 實現方案
      • 2.2 網絡傳輸的參數和返回值怎么映射到對應的RPC接口上?
        • 方法一:使用 protobuf 的反射機制
        • 方法二:使用 C++ 模板、類型萃取、函數萃取等機制
        • 方法三:使用更通用的類型(如 JSON)
        • 🌈 技術方案對比
      • 2.3 網絡傳輸怎么做?
      • 2.4 序列化和反序列化?
    • 三、環境搭建
      • 3.1 Centos 7.6 環境搭建
      • 3.2 Ubuntu 22.04 環境搭建


一、項目介紹

🔥 RPC(Remote Procedure Call)遠程過程調用,是一種通過網絡從遠程計算機上請求服務,而不需要了解底層網絡通信細節。

  • RPC 可以使用多種網絡協議進行通信,如HTTP、TCP、UDP等,并且在 TCP/IP 網絡四層模型中跨越了傳輸層和應用層。簡言之RPC就是像調用本地方法一樣調用遠程方法
  • 過程可以理解為業務處理、計算任務,更直白的說,就是程序/方法/函數等,就是像調用本地方法一樣調用遠程方法

image-20250312152552022

💬 通俗類比:通信方式的進化

+ 本地調用:情侶同城約會- 隨時見面(低延遲)- 直接交流(無需協議)+ RPC調用:跨國網戀奔現  ?? 約定時間(服務發現)📨 發送航班信息(序列化)🛃 海關檢查(協議校驗)💌 最終見面(反序列化)

一個完整RPC通信框架,大概包含以下內容

  • 序列化協議
  • 通信協議
  • 連接復用
  • 服務注冊
  • 服務發現
  • 服務訂閱和通知
  • 負載均衡
  • 服務監控
  • 同步調用
  • 異步調用

我們的項目是基于C++、JsonCpp、muduo網絡庫實現一個簡單、易用的RPC通信框架,即使是不懂網絡的開發者也可以很快速的上手,它實現了同步調用、異步callback 調用、異步 futrue調用、服務注冊/發現,服務上線/下線以及發布訂閱等功能設計。

二、技術選型

2.1 RPC 實現方案

目前RPC的實現方案有兩種:

  1. clientserver 繼承公共接口

    • 根據 IDL(接口描述語言)定義公共接口
    • 編寫代碼生成器根據IDL語言生成相關的C++、Java代碼然后我們的客戶端和服務器程序共同向上繼承公共接口即可
    • 比如:我們常用的Protobuf、ison可以定義IDL接口,并生成RPC相關的代碼
    • 缺點:使用pb因為生成一部分代碼,所以對理解不夠友好;如果是json定義IDL語言 需要自己編寫代碼生成器難度較大一點,暫不考慮這種方案
  2. 實現?個遠程調用接口cal,,然后通過傳入函數名參數來調用RPC接口,我們采用這種實現方案

image-20250312154155524

2.2 網絡傳輸的參數和返回值怎么映射到對應的RPC接口上?

方法一:使用 protobuf 的反射機制

原理

protobuf 是一種高效的序列化協議,支持通過 .proto 文件定義數據結構。protobuf 提供了反射機制,允許程序在運行時動態獲取消息的字段信息(如字段名、類型等)。通過反射機制,可以將網絡傳輸的參數和返回值動態映射到對應的RPC接口。

實現步驟

  1. 定義 .proto 文件 :描述RPC接口的請求和響應數據結構。
  2. 生成代碼 :使用 protoc 工具生成對應語言的代碼(如C++、Python等)。
  3. 利用反射機制 :
    • 在運行時,通過反射機制解析請求和響應的字段。
    • 動態調用對應的RPC接口,并將解析后的數據作為參數傳遞。
  4. 序列化和反序列化 :將請求和響應數據序列化為二進制格式進行傳輸。

優點

  • 高效:protobuf 序列化效率高,占用帶寬小。
  • 強類型:編譯時檢查字段類型,減少運行時錯誤。
  • 易擴展:通過 .proto 文件輕松擴展字段。

缺點

  • 學習成本較高:需要熟悉 .proto 文件和反射機制。
  • 動態性有限:反射機制雖然靈活,但仍需依賴預定義的 .proto 文件。

Mermaid

Client Server ProtoReflection 定義.proto文件并生成代碼 提供反射接口 序列化請求數據(protobuf) 反序列化請求數據 使用反射解析字段 調用對應RPC接口 序列化響應數據 返回響應數據 Client Server ProtoReflection

方法二:使用 C++ 模板、類型萃取、函數萃取等機制

原理

C++ 模板元編程允許在編譯時對類型進行操作,而類型萃取和函數萃取則用于提取函數的參數和返回值類型。通過這些機制,可以在編譯時自動推導出RPC接口的參數和返回值類型,從而實現參數和返回值的映射。

實現步驟

  1. 定義RPC接口 :使用C++函數定義RPC接口。
  2. 使用模板萃取 :
    • 利用 std::function 或模板函數提取函數的參數和返回值類型。
    • 定義通用的包裝器(Wrapper),將參數和返回值映射到網絡傳輸的格式。
  3. 序列化和反序列化 :
    • 將參數序列化為網絡傳輸格式(如JSON或自定義二進制格式)。
    • 在服務端反序列化后,調用對應的RPC接口。
  4. 返回結果 :將返回值序列化并發送回客戶端。

優點

  • 高性能:所有類型推導和映射在編譯時完成,運行時開銷低。
  • 靈活性強:支持任意類型的參數和返回值。
  • 類型安全:編譯時檢查參數和返回值類型。

缺點

  • 復雜度高:需要熟悉C++模板元編程和類型萃取機制。
  • 不易調試:模板代碼在編譯時展開,調試難度較大。

MerMaid

Client Server TemplateMechanism 定義RPC接口 提取參數和返回值類型 序列化請求數據(JSON/自定義格式) 反序列化請求數據 調用對應RPC接口 序列化響應數據 返回響應數據 Client Server TemplateMechanism
方法三:使用更通用的類型(如 JSON)

原理

JSON 是一種輕量級的數據交換格式,具有良好的可讀性和跨語言支持。通過設計一套通用的參數和返回值協議,可以將網絡傳輸的數據統一表示為JSON格式,從而簡化參數和返回值的映射。

實現步驟

  1. 設計協議 :
    • 定義請求和響應的JSON結構,包括字段名、類型和含義。
    • 例如,請求可能包含 method(接口名)、params(參數列表)等字段。
  2. 序列化和反序列化 :
    • 客戶端將參數序列化為JSON格式并發送。
    • 服務端解析JSON數據,提取參數并調用對應的RPC接口。
  3. 返回結果 :
    • 服務端將返回值序列化為JSON格式并發送回客戶端。

優點

  • 簡單易用:JSON格式直觀,易于理解和實現。
  • 跨語言支持:幾乎所有的編程語言都支持JSON解析。
  • 動態性強:無需提前定義固定的數據結構。

缺點

  • 性能較低:JSON序列化和反序列化效率低于二進制格式。
  • 類型不安全:JSON是弱類型格式,可能導致運行時錯誤。

MerMaid

Client Server JSONProtocol 設計請求和響應協議 序列化請求數據為JSON 發送JSON請求 解析JSON請求 調用對應RPC接口 序列化響應數據為JSON 返回JSON響應 Client Server JSONProtocol
🌈 技術方案對比
方案核心技術優點缺點
Protobuf反射利用.proto文件的元數據描述強類型安全,跨語言支持需要IDL編譯,C++實現較復雜
模板元編程類型萃取+函數簽名解析零運行時開銷,類型嚴格匹配代碼可讀性差,調試困難
JSON通用協議動態類型系統+預定義協議格式開發簡單,易擴展,可視化調試類型安全性需運行時校驗
  • 由于前兩種技術難度和學習成本較高,因此這個項目我們使用第三種方式

2.3 網絡傳輸怎么做?

  • 原生socket :實現難度較大,暫不考慮
  • Boost asio庫的異步通信:需要擴展boost庫
  • muduo庫:和當前項目對應,學習開發成本較低

2.4 序列化和反序列化?

  • Protobuf:可選
  • JSON:因為項目需要使用 JSON 來定義函數參數和返回值,所以項目中直接采用 JSON 進行序列化和反序列化

三、環境搭建

3.1 Centos 7.6 環境搭建

① 安裝 wget

sudo yum install wget

② 更新軟件源

sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak
sudo wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.reposudo yum clean all # 清理緩存信息
sudo yum makecache

③ 安裝 scl 軟件源

sudo yum install centos-release-scl-rh centos-release-scl

④ 安裝 epel 軟件源

sudo yum install epel-release

⑤ 安裝 lrzsz 傳輸工具

sudo yum install lrzsz
rz --version
rz (lrzsz) 0.12.20

⑥ 安裝高版本 gcc/g++ 編譯器

sudo yum install devtoolset-7-gcc devtoolset-7-gcc-c++
echo "source /opt/rh/devtoolset-7/enable" >> ~/.bashrc
source ~/.bashrc
g++ -v

⑦ 安裝 Jsoncpp 庫

sudo yum install jsoncpp-devells /usr/include/jsoncpp/json/
assertions.h autolink.h config.h ...

⑧ 安裝 cmake

sudo yum install cmakecmake --version
cmake version 2.8.12.2

⑨ 安裝 Muduo

  • 下載源碼
# git?式
[zsc@node ~]$ git clone https://github.com/chenshuo/muduo.git
  • 修復 muduo 庫 安裝 protorpc 的時候沒有安裝
/muduo-master/muduo/net/protorpc/CMakeLists.txt
  • 安裝依賴環境
sudo yum install make boost-devel

當前上面步驟還是過于多了,我們可以直接 運行腳本編譯安裝

腳本鏈接:https://gitee.com/qigezi/bitrpc/blob/master/third/muduo-master.zip

然后把腳本下載之后導入解包,按照下面指令編譯安裝即可

./build.sh
./build.sh install

3.2 Ubuntu 22.04 環境搭建

① 安裝 wget – 一般默認情況下都有

sudo apt-get install wget

② 更新國內軟件源

先備份原來的 /etc/apt/source.list 文件

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak# 比如
lighthouse@VM-8-10-ubuntu:~$ sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
lighthouse@VM-8-10-ubuntu:~$ ls /etc/apt/
apt.conf.d   keyrings       sources.list      sources.list.curtin.old  trusted.gpg.d
auth.conf.d  preferences.d  sources.list.bak  sources.list.d

添加軟件源文件內容,新增以下內容

# 先打開源文件
sudo vi /etc/apt/source.listdeb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse
#添加清華源 
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse

新增完畢后,更新源

sudo apt-get update

③ 安裝 lrzsz 傳輸工具

sudo apt-get install lrzsz
rz --version
rz (lrzsz) 0.12.20

④ 安裝高版本 gcc/g++ 編譯器

sudo apt-get install gcc g++

⑤ 安裝項目構建工具 make 和 cmake

sudo apt-get install makesudo apt-get install cmake
cmake --version
cmake version 3.22.1

⑥ 安裝調試器 gdb

sudo apt-get install gdb

⑦ 安裝 git

sudo apt-get install git
git --versio

⑧ 安裝 Jsoncpp 庫

sudo apt-get install libjsoncpp-dev# 安裝成功之后
ls /usr/include/jsoncpp/json/
allocator.h   config.h    json_features.h  reader.h  version.h
assertions.h  forwards.h  json.h           value.h   writer.h

⑨ 安裝 Muduo

  • 下載源碼
# git?式
[zsc@node ~]$ git clone https://github.com/chenshuo/muduo.git
  • 安裝依賴環境
sudo apt-get install libz-dev libboost-all-dev

運行腳本編譯安裝

unzip muduo-master.zip
./build.sh
./build.sh install

參考

https://zhuanlan.zhihu.com/p/460646015

https://zhuanlan.zhihu.com/p/33298916

源碼:https://github.com/cinemast/libjson-rpc-cpp

      value.h   writer.h

⑨ 安裝 Muduo- 下載源碼 ```bash
# git?式
[zsc@node ~]$ git clone https://github.com/chenshuo/muduo.git
  • 安裝依賴環境
sudo apt-get install libz-dev libboost-all-dev

運行腳本編譯安裝

unzip muduo-master.zip
./build.sh
./build.sh install

參考

https://zhuanlan.zhihu.com/p/460646015

https://zhuanlan.zhihu.com/p/33298916

源碼:https://github.com/cinemast/libjson-rpc-cpp

源碼:https://github.com/qicosmos/rest_rpc

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

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

相關文章

WPF輪播圖動畫交互 動畫縮放展示圖片

WPF輪播圖動畫交互 動畫縮放展示圖片 效果如下圖&#xff1a; XAML代碼&#xff1a; <Window x:Class"Caroursel.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/20…

為什么 npm list -g 沒顯示 node_modules??

揭秘&#xff1a;為什么 npm list -g 沒顯示 node_modules&#xff1f;&#x1f575;??♂?? 嗨&#xff0c;各位代碼探險家&#xff01;&#x1f44b; 今天我們要破解一個 npm 小謎團&#xff1a;運行 npm list -g --depth0 時&#xff0c;為什么輸出的路徑里看不到 node_…

都江堰與鄭國渠

目錄標題 一、歷史背景&#xff1a;地緣博弈下的水利突圍都江堰&#xff1a;化水患為天府的千年大計鄭國渠&#xff1a;間諜引發的戰略反轉 二、工程智慧&#xff1a;超越時代的科技奇跡都江堰&#xff1a;生態治水的典范鄭國渠&#xff1a;泥沙資源化的創舉 三、后世影響&…

鏈路聚合+vrrp

1.鏈路聚合 作用注意事項將多個物理接口&#xff08;線路&#xff09;邏輯上綁定在一起形成一條邏輯鏈路&#xff0c;起到疊加帶寬的作用1.聚合接口必須轉發速率一致。2.聚合設備兩端必須一致 配置命令 方法一 [Huawei]interface Eth-Trunk 0----先創建聚合接口&#xff0c;…

【STM32單片機】#7 定時器輸入捕獲

主要參考學習資料&#xff1a; B站江協科技 STM32入門教程-2023版 細致講解 中文字幕 開發資料下載鏈接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 單片機套裝&#xff1a;STM32F103C8T6開發板單片機C6T6核心板 實驗板最小系統板套件科協 實驗&…

【android bluetooth 框架分析 01】【關鍵線程 3】【bt_jni_thread 線程介紹】

1. bt_jni_thread 職責介紹 bt_jni_thread 這個線程的作用是專門負責處理藍牙 JNI 層的消息循環&#xff0c;也可以說是 C 層和 Java 層交互的橋梁線程。 1.1 什么是 JNI 層&#xff1f;為什么需要這個線程&#xff1f; JNI&#xff08;Java Native Interface&#xff09;是 …

基于視覺語言模型的機器人實時探索系統!ClipRover:移動機器人零樣本視覺語言探索和目標發現

作者&#xff1a;Yuxuan Zhang 1 ^{1} 1, Adnan Abdullah 2 ^{2} 2, Sanjeev J. Koppal 3 ^{3} 3, and Md Jahidul Islam 4 ^{4} 4單位&#xff1a; 2 , 4 ^{2,4} 2,4佛羅里達大學電氣與計算機工程系RoboPI實驗室&#xff0c; 1 , 3 ^{1,3} 1,3佛羅里達大學電氣與計算機工程系F…

SpringBoot和微服務學習記錄Day2

微服務 微服務將單體應用分割成更小的的獨立服務&#xff0c;部署在不同的服務器上。服務間的關聯通過暴露的api接口來實現 優點&#xff1a;高內聚低耦合&#xff0c;一個模塊有問題不影響整個應用&#xff0c;增加可靠性&#xff0c;更新技術方便 缺點&#xff1a;增加運維…

網站集群批量管理-Ansible劇本與變量

復盤內容&#xff1a;鏈接指北 查看ansible命令文檔 ansible-doc -s systemd一、劇本 何為劇本: playbook 文件,用于長久保存并且實現批量管理,維護,部署的文件. 類似于腳本存放命令和變量 劇本yaml格式,yaml格式的文件:空格,冒號. 劇本未來我們批量管理,運維必會的內容. …

如何在Dify中安裝運行pandas、numpy庫(離線、在線均支持,可提供遠程指導)

pandas和numpy這兩個庫是數據科學和數據分析中經常使用的工具包&#xff0c;原生的Dify無法直接使用這兩個庫&#xff0c;需要手動安裝后才可以使用。本文將介紹如何在Dify中安裝pandas和numpy&#xff0c;并在代碼執行節點中運行使用pandas和numpy。 Dify的代碼執行節點中的py…

Helm核心概念與常見操作介紹

在管理Kubernetes集群里的應用時&#xff0c;Helm能幫上大忙&#xff0c;它把應用的部署、升級和管理變得簡單多了&#xff0c;有如是Kubernetes的 “應用商店”。 Helm的三個重要概念 三大概念最直接的理解&#xff1a;Helm 安裝 charts 到 Kubernetes 集群中&#xff0c;每…

rkmpp 解碼 精簡mpi_dec_test.c例程

rkmpp 解碼流程&#xff08;除 MPP_VIDEO_CodingMJPEG 之外&#xff09; 源碼 輸入h264碼流 輸出nv12文件 /** Copyright 2015 Rockchip Electronics Co. LTD** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file exce…

用一個實際例子快速理解MCP應用的工作步驟

已經有很多的文章介紹MCP server&#xff0c;MCP Client工作原理&#xff0c;這里不做太多介紹。但是很多介紹都只是側重介紹概念&#xff0c;實際的工作原理理解起來對初學者還是不太友好。本文以一個智能旅游咨詢系統為例&#xff0c;詳細說明在利用 Model Context Protocol&…

【LeetCode 題解】數據庫:1321.餐館營業額變化增長

一、問題描述 本題給定了一個名為 Customer 的表&#xff0c;記錄了餐館顧客的交易數據&#xff0c;包括顧客 ID、姓名、訪問日期和消費金額。作為餐館老板&#xff0c;我們的任務是分析營業額的變化增長情況&#xff0c;具體來說&#xff0c;就是計算以 7 天&#xff08;某日…

【Python】讀取xlsb或xlsx的單一或連續單元格工具類

代碼主要來自Kimi.ai&#xff0c;有修改。 優先使用工作表序號索引工作表&#xff0c;序號從1開始。 運行需要先安裝openpyxl和pyxlsb兩個第三方庫。 import openpyxl from openpyxl.utils import range_boundaries from pyxlsb import open_workbook as open_xlsbclass Exc…

【藍橋杯】動態規劃:背包問題

這篇文章主要記錄動態規劃方面的學習。 動態規劃的核心思想: 把大問題分解成小問題,記住小問題的解,避免重復計算。 動態規劃(DP)的三大特點: ①最優子結構:大問題的最優解可以由小問題的最優解推導出來 ②重疊子問題:在求解過程中會反復遇到相同的小問題 ③無后效…

華為數字芯片機考2025合集1已校正

單選 1&#xff0e;以下低功耗措施中&#xff0c;哪種不是降低電路翻轉率的方法? A.在不進行算術運算的時候&#xff0c;使這些模塊的輸入保持不變&#xff0c;不讓新的操作數進來 B.采用Gray 碼或One‐hot 碼作為狀態機編碼 C.減少電路中的glitch D.重新安排“if‐else”表達…

React 列表渲染

開發環境&#xff1a;Reacttsantd 你可能經常需要通過 JavaScript 的數組方法 來操作數組中的數據&#xff0c;從而將一個數據集渲染成多個相似的組件。在這篇文章中&#xff0c;你將學會如何在 React 中使用 filter() 篩選需要渲染的組件和使用 map() 把數組轉換成組件數組。 …

力扣刷題DAY11(動態規劃-線性DP)

一、最長上升子序列 300. 最長遞增子序列 &#xff08;一&#xff09;初版代碼 class Solution { public:int lengthOfLIS(vector<int>& nums) {int n nums.size();vector<int> f(n 1, 1); //初始化為1&#xff0c;因為每個數至少可以作為一個單獨的序列in…

DFS--

數字的全排列 #include <bits/stdc.h> using namespace std;//最大的排列數目 const int N10; int n; //存儲排列的路徑 int path[N]; //標記數字是否已經被使用 bool st[N];void dfs(int u){//到達遞歸邊界&#xff0c;輸出一個排列if(un){//輸出循環for(int i0; i<…