開源2年半了,一直都還沒給SRPC系統地寫過什麼文章。
趁著最近釋出了srpc構建小工具,也給SRPC寫幾篇交流學習文件,
希望單獨的每一篇都能讓不同程度的小夥伴有所收穫~~~
1. 從srpc小工具開始
最近給SRPC框架做了一個小工具:用於快速構建Workflow和SRPC專案的腳手架,旨在降低專案使用門檻,解決大部分零基礎開發者第一次面對cmake檔案編寫、lib的依賴、編譯與執行環境等容易遇到的問題。
srpc小工具,讓開發者的三個步驟:構建 - 編譯 - 執行,都變得更簡單(叉腰!
SRPC地址:https://github.com/sogou/srpc
另外,懶了好久沒po文,新小夥伴可能比較多,以下補充一些可以跳過的背景知識。
SRPC是一個輕量級、企業級、效能優異的RPC框架,程式碼結構精巧解耦合,跟隨原始碼看請求過程一氣呵成,非常適合用來學習RPC架構,部署使用也都比較方便。
而SRPC又是基於Workflow開發的,Workflow目前已經是一個萬星專案、成為Debian / Ubuntu Linux / Fedora等系統的自帶安裝包,也獲得了大家還不錯的口碑,所以就不多介紹了。等這列文章完結之後,我會再開展Workflow的學習系列,如果對底層網路模型、計算排程做法、任務流設計等感興趣的小夥伴,需要再給一丟丟耐心等待~
Workflow地址:https://github.com/sogou/workflow
2. 一行命令構建起你的專案
2.1 原始碼位置
我們把上述的專案clone下來,並開啟tools目錄,就可以編譯出我們的srpc小工具。工具名字也叫srpc,但是是小寫的~
git clone https://github.com/sogou/srpc.git
cd srpc/tools && make
這個小工具和SRPC框架目前還沒有關係,所以即使本地沒有安裝SRPC所需要的protobuf或者不加--recursive拉submodule下來,也依然可以編譯。唯一需要的是cmake 3.6及以上的版本。
2.2 執行工具
我們先把這個srpc小工具執行起來,可以看到它第二個引數COMMAND:表示支援什麼命令。
./srpc
Description:
Simple generator for building Workflow and SRPC projects.
Usage:
./srpc <COMMAND> <PROJECT_NAME> [FLAGS]
Available Commands:
http - create project with both client and server
redis - create project with both client and server
rpc - create project with both client and server
proxy - create proxy for some client and server protocol
file - create project with asynchronous file service
compute - create project with asynchronous computing service
這些COMMAND包括了我們最常用的場景,適合入門瞭解伺服器程式設計最簡單的內容。
2.3 一行命令構建專案
第三個引數是專案名,我們先用一行簡單的命令,構建出一個Http伺服器與客戶端。
./srpc http my_project
Success:
make project path " my_project/ " done.
Commands:
cd my_project/
make -j
Execute:
./server
./client
可以看到提示Success!
2.4 第一個專案的編譯和執行
我們按照上述的提示看到:my_project目錄已經在本地目錄下建立,並給出了:
- 編譯的命令:make
- 執行的命令:分別在兩個終端上執行./server 和 ./client
cd my_project
make
執行ls -all
一下可以看到,兩個可執行檔案已經編譯出來了。我們分別在兩個終端執行./server
和./client
:
./server
Http server started, port 8080
http server get request_uri: /client_request
peer address: 127.0.0.1:65313, seq: 0.
client執行起來後會給server發一個請求,然後server會列印出上面顯示的最後兩行,然後client收到回覆之後也會列印下面的兩行:
./client
Http client state = 0 error = 0
<html>Hello from server!</html>
2.5 模組依賴,是C++專案的第一道門檻
剛才git clone專案時沒有加--recursive拉取依賴的submodule,且srpc的lib是還沒有沒有編譯的,那麼其實工具都自動會幫做這些初始化的工作。
當然,目前C++跟GO等其他語言比起來在構建方面還是薄弱了一點。如果大家還沒有安裝protobuf,或者系統的版本太舊、導致編譯SRPC時所依賴的protobuf版本與連結時不一樣,那麼可以先使用原始碼編譯protobuf。
這裡找了一個不太新也不太舊的版本,供需要安裝protobuf的小夥伴參考:
git clone -b 3.20.x https://github.com/protocolbuffers/protobuf.git protobuf.3.20
cd protobuf.3.20
sh autogen.sh
./configure
make -j4
make install
然後我們就可以愉快再試一下上述步驟了~
3. 一個腳手架專案包含了什麼?
我們執行tree
命令,檢視這個專案裡的檔案結構。
需要我們關注的有這些:
3.1 編譯檔案
腳手架小工具目前還是使用cmake進行編譯,後續計劃支援bazel和xmake。
GNUmakefile
包了一層cmake命令,讓我們可以執行make
就編譯出專案,這個檔案我們不需要關心。
開啟CMakeLists.txt
,可以看到一共32行,包括了:
- 尋找依賴路徑的寫法
- include和link的寫法
- 編出執行檔案
開發者可以根據裡邊的註釋自行修改,即使不常用C++的開發者也可以邊試邊學。
3.2 client
client會讀取client.conf
作為它的配置檔案,主要是指定要訪問的目標是什麼。
我們開啟client_main.cc
,可以看到腳手架預設生成的client只有60多行,一共做了3件事:
int main()
{
// 1. 初始化,這個實現也在原始碼中,主要是呼叫config.load("./client.conf")
init();
std::string url = std::string("http://") + config.client_host() +
std::string(":") + std::to_string(config.client_port());
// 2. 構造一個http task並且填回撥函式
WFHttpTask *task = WFTaskFactory::create_http_task(url,
config.redirect_max(),
config.retry_max(),
callback);
// 3. 把task執行起來
task->start();
wait_group.wait();
return 0;
}
可以看到,這個和workflow的tutorial中的例子是一樣的,需要填的callback函式也在檔案中。
3.4 server
我們開啟server_main.cc
,50多行的程式碼,也是做了3件事,可以看到和上面的client是非常對稱的:
int main()
{
// 1. 初始化,這個實現也在原始碼中,主要是呼叫config.load(“./server.conf")
init();
// 2. 造一個server,填好處理函式
WFHttpServer server(process);
// 3. 把server執行起來
if (server.start(config.server_port()) == 0)
{
fprintf(stderr, "Http server started, port %u\n", config.server_port());
wait_group.wait();
server.stop();
}
else
perror("server start");
return 0;
}
process函式也在原始碼中,開發者可以嘗試修改,進行不同的行為處理。示例中的行為就是回覆一個 " Hello from server! "
3.5 配置檔案
配置解析並不是Workflow和SRPC專案自帶的,但是腳手架專案增加了這個功能。
我們目前使用的配置檔案都是json格式,和配置解析相關的都放到了config目錄中。除了client.conf和server.conf以外,我們還多加了一份full.conf,用來指引Workflow和SRPC目前支援的配置項,開發者可以通配置檔案,快速瞭解我們還可以用什麼功能。
比如框架的全域性配置:
{
"server":
{
"port": 8080
},
"client":
{
"remote_host": "127.0.0.1",
"remote_port": 8080,
"retry_max": 1,
},
"global":
{
"poller_threads": 4,
"handler_threads": 20
}
}
熟悉的開發者可能接觸過Workflow的upstream,以及trace和metrics等監控資料的上報外掛,這些都可以在配置檔案中指定並一鍵載入,幫開發者接管外部生態,真正實現腳手架的能力。
4. 命令大全
經過以上介紹,應該可以基本掌握怎麼快速構建和執行一個自己的小專案。接下來我們進一步解鎖這個srpc小工具,每個COMMAND都是一個二級命令。
4.1 rpc命令
構建一個以protobuf或者thrift作為IDL的多協議RPC專案。
如果先前沒有了解過SRPC的小夥伴,有空可以圍觀一下這份wiki:SRPC架構介紹 - Sogou基於Workflow的自研RPC框架,也可以這裡用一句話簡述一下:
SRPC框架支援:
- 多種協議
- 多種IDL
- 多種資料格式
- 多種壓縮演算法
我們的client和server只需要保證以同樣的協議進行通訊,而其餘的東西交給SPRC框架幫你處理就好,最終開發者接觸到的就是我們的IDL所約定的介面,比如在xxx.proto
檔案中長這樣:
service rpc_test {
rpc Echo(EchoRequest) returns (EchoResponse);
};
其中,支援的RPC協議包括:SRPC、SRPCHttp、BRPC、TRPC、TRPCHttp、Thrift、ThriftHttp。
這些東西都可以在構建時透過引數指定。
我們執行./srpc rpc
,就可以看到rpc命令支援的引數:
我們嘗試以預設方式構建一個RPC專案。也可以使用-f
指定IDL檔案進行構建,這會使用srpc_generator
去進行程式碼生成。
./srpc rpc rpc_project
開啟之後,可以看到和Http相比,有如下區別:
- 多了一個
rpc_project.proto
- server_main.cc和client_main.cc分別變成了SRPCServer和SRPCClient;
- CMakeLists.txt也變複雜了,因為需要依賴protobuf和snappy等壓縮庫;
但我們依然可以透過make
把專案編譯出來。執行方式與前面類似,不再贅述。
4.2 redis命令
這個命令主要用於構建redis協議的server和client,由於Workflow的協議對server和client來說都是對等的,因此基於Workflow實現的redis server依然非常簡潔高效。
這個例子中,client發出的請求是set k1 v1
,server收到任何內容都回復一個OK
。並且client.conf中增加了使用者名稱和密碼的項,開發者可以透過修改配置,用這個client訪問其他任意的redis server。
4.3 proxy : 代理伺服器
代理伺服器顧名思義,就是可以多構建一個proxy,我們可以用client去訪問proxy,並由proxy去轉發給server,這中間proxy就可以做很多事情,包括:更改協議、內容校驗等等。
一個常見的場景是,我們的現有業務是客戶端發出TRPC協議,而需要訪問SRPC協議的伺服器時,則可以構建出一個TRPC-SRPC的proxy,並且讓大家使用統一的proto檔案約定好請求,則proxy就可以直接做轉發。
我們執行如下命令,用-c
指定client端的協議,用-s
指定server端的協議:
./srpc proxy proxy_project -c trpc -s srpc
然後還是按照前面所述的編譯和執行。這裡我們分別執行起來./server
,./proxy
和./client
:
而proxy_main.cc
的實現,是起了一個TRPCServer,並使用SRPCClient去轉發請求。感興趣的小夥伴可以圍觀一下,其實SRPC專案的tutorial裡也已經有這樣的例子了:tutorial-15-srpc_pb_proxy.cc
4.4 file : 檔案伺服器
檔案伺服器透過非同步IO讀取,也是我們常用的功能,這裡不再贅述,對實現感興趣的小夥伴歡迎檢視原先的一篇文章:《Workflow程式設計小示例4: 轉發伺服器與series上下文的使用》
我們透過./srpc file file_project
構建一下專案,我們可以透過curl命令去讀取想要的檔案,例如curl localhost:8080/index.html
就可以讀取到指定root目錄下的index.html檔案。
可以看到,多了一個html
的目錄,裡邊放了index.html
, 404.hmtl
和50x.html
。如果使用過其他Http伺服器的小夥伴應該不陌生,這是常見的用法。
.
├── CMakeLists.txt
├── GNUmakefile
├── config
│ ├── Json.cc
│ ├── Json.h
│ ├── config.cc
│ └── config.h
├── file_service.cc
├── file_service.h
├── html
│ ├── 404.html
│ ├── 50x.html
│ └── index.html
├── server.conf
└── server_main.cc
3 directories, 13 files
我們還可以透過配置檔案去指定具體錯誤碼對應的錯誤頁面,而錯誤頁面和其他檔案一樣,都是透過非同步IO的方式讀取,不會阻塞server當前的處理執行緒。
熟悉的error_page,它來了:
{
"server":
{
"port": 8080,
"root": "./html/",
"error_page" : [
{
"error" : [ 404 ],
"page" : "404.html"
},
{
"error" : [ 500, 502, 503, 504],
"page" : "50x.html"
}
]
}
}
4.5 compute : 計算伺服器
計算伺服器也是透過go_task發起計算任務,不會阻塞當前執行緒。實現原理歡迎參考:《WF程式設計小示例6: 計算型伺服器與計算任務》
5. 其他
srpc小工具的基本用法就介紹完了,但是由於它剛剛面世,之後會支援命令還會更多,支援的配置也會更多,比如error_page這種大家習慣的配置用法,22同學都會想想怎麼加上~
希望這個小工具可以減少開發者第一次接觸專案時,“構建 - 編譯 - 執行”所面臨的困難,而SRPC專案之後也將致力於降低開發者使用門檻,包括最佳化依賴庫和submodule、提供更多編譯方式、支援更多好用的生態外掛等等。
當然這系列的學習文章也是降低使用門檻、陪伴小夥伴們學習程式碼、獲取大家反饋促進交流的重要一環,之後爭取周更,把這系列的坑填完!所以想要看什麼內容或者對srpc小工具有什麼建議要提的都得趕緊了~
最後附上github上的文件:https://github.com/sogou/srpc/blob/master/tools/README.md