開源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