做者丨張勇
編輯丨TARS小助手
Tars是騰訊從2008年到今天一直在使用的微服務開發框架,2018年成爲Linux基金會開源項目,目前支持C++、Java、PHP、NodeJS與Go語言。該框架爲用戶提供了涉及到開發、運維,以及測試的一整套解決方案,幫助一個產品或者服務快速開發、部署、測試、上線。它集可擴展協議編解碼、高性能RPC通訊框架、名字路由與發現、發佈監控、日誌統計、配置管理等於一體,經過它能夠快速用微服務的方式構建本身的穩定可靠的分佈式應用,並實現完整有效的服務治理。php
TarsPHP做爲Tars在PHP語言的解決方案,設計的時候主要考慮以下四個方面:mysql
Protocol buffers (簡稱PB)是Google開源的語言中立,平臺無關,可擴展的序列化數據的格式,可用於通訊協議,數據存儲等。它和XML相似,但比XML更小,更快,更簡單。linux
PB是編碼協議,若是涉及到網絡傳輸和RPC調用,就須要引入通信協議。Google開源的RPC框架gRPC就使用Http2做爲通信協議,PB做爲編碼協議。git
Protoc 安裝github
首先須要安裝protoc庫,這個庫的主要做用是打包解包protobuf協議數據。能夠參考 https://github.com/protocolbu... 直接安裝。sql
./autogen.sh ./configure make make install
若是 protoc –version 能夠正常輸出,說明安裝完成json
php protobuf安裝後端
以後須要安裝 php protobuf擴展,這個擴展主要用做php和protoc庫中間的一個橋樑。api
git clone https://github.com/protocolbuffers/protobuf.git cd ./php/ext/google/protobuf/ phpize ./configure make make install (須要編輯php.ini文件,開啓protobuf擴展)
若是 php –ri protobuf 有輸出,說明安裝正常。服務器
Swoole 安裝
建議使用4.4.0或以上版本,須要開啓http2 和 openssl支持。
參考TarsPHP中ActDemo中評論服務的tars文件,咱們寫了一個actComment.proto的協議文件。
和tars協議文件不一樣,proto協議中規定輸入輸出參數必須也只能是一個message結構體,所以須要對輸入輸出參數單獨在封裝一個message。
syntax = "proto3"; package protocol.QD.ActCommentPbServer; //包名,會根據包名生成 php類路徑 service CommentObj { rpc ping(PingRequest) returns (PingResponse) {}; rpc getCommentCount(CountRequest) returns (CountResponse) {}; rpc createComment(CreateRequest) returns (CreateResponse) {}; rpc getComment(GetRequest) returns (GetResponse) {}; } //輸入參數通用結構體 message CommonInParam { int32 appId = 1; int32 areaId = 2; int64 userId = 3; //用戶信息 string userIp = 4; //來源名稱 string serverIp = 5; //調用方服務器ip }; //輸出參數通用結構體 message CommonOutParam { int32 code = 1; //接口返回碼 string message = 2; //接口返回提示信息 }; message SimpleComment { int32 id = 1; int64 activityId = 2; int64 userId = 3; string content = 4; string title = 5; string ext1 = 6; int64 createTime = 7; }; message QueryParam { int64 activityId = 1; int32 page = 2; int32 size = 3; int32 orderType = 4; }; message CreateRequest { CommonInParam inParam = 1; SimpleComment comment = 2; }; message CreateResponse { CommonOutParam outParam = 1; }; message GetRequest { CommonInParam inParam = 1; QueryParam queryParam = 2; }; message GetResponse { CommonOutParam outParam = 1; repeated SimpleComment list = 2; }; message PingRequest { }; message PingResponse { }; message CountRequest { }; message CountResponse { int32 count = 1; };
protoc能夠根據proto文件生成對應的php類代碼,可是官方並不支持proto文件生成server端代碼,能夠使用gRPC插件生成client代碼。若是須要使用生成的client代碼咱們還須要安裝grpc庫和grpc php擴展。
所以咱們的思路是,先使用protoc生成php須要的類,而後本身解析proto文件生成server 端interface,這個過程很是像現有的tars2php的過程,所以咱們叫它proto2php。
因爲使用兩個工具生成還比較麻煩,咱們把調用proto的過程集成到proto2php中方便你們使用。
咱們先構建一個tars.proto.php設置一些基本信息。
return array( 'appName' => 'QD', 'serverName' => 'ActCommentPbServer', 'objName' => 'CommentObj', 'withServant' => true, //決定是服務端,仍是客戶端的自動生成 'tarsFiles' => array( './actComment.proto', ), 'dstPath' => '../src/protocol', //這裏指定的是 impl 基礎interface 生成的位置 'protocDstPath' => '../src', //這裏指定的是 protoc 生成的問題 'namespacePrefix' => 'Protocol', );
而後執行 php …/src/vendor/phptars/tars2php/src/proto2php.php ./tars.proto.php
以後會生成GPBMetadata目錄和protocol目錄。其中protocol中就是proto文件生成的php類,另外CommentObjServant.php就是proto2php文件生成的server端interface類。構建TarsPHP pb server須要實現這個類。
按照Demo中 Readme部署tarsphp pb server便可。
幾點注意:
{ "name" : "tars-tcp-server-demo", "description": "tars tcp server", "require": { "phptars/tars-server": "~0.3", "phptars/tars-deploy": "~0.1", "phptars/tars-log": "~0.1", "phptars/tars2php": "~0.1", "ext-zip" : ">=0.0.1", "google/protobuf": "^3.8" }, "autoload": { "psr-4": { "Server\\" : "./", "Protocol\\" : "./protocol", "GPBMetadata\\" : "./GPBMetadata" } }, "minimum-stability": "stable", "scripts" : { "deploy" : "\\Tars\\deploy\\Deploy::run" } }
最後執行 composer run-script deploy,生成代碼包,上傳到Tars平臺上發佈。
能夠使用gRPC生成的php客戶端訪問測試,也能夠直接使用swoole 的http2客戶端構建一個grpc客戶端。
class TestGrpcClient { public static function callGrpc($ip, $port, $path, $requestBuf) { $cli = new Swoole\Coroutine\Http2\Client($ip, $port, false); $cli->connect(); $req = new swoole_http2_request; $req->method = 'POST'; $req->path = $path; $req->headers = [ "user-agent" => 'grpc-c/7.0.0 (linux; chttp2; gale)', "content-type" => "application/grpc", "grpc-accept-encoding" => "identity,deflate,gzip", "accept-encoding" => "identity,gzip", "te" => "trailers", ]; $req->pipeline = false; $req->data = $requestBuf; $cli->send($req); $response = $cli->recv(); return $response->data; } public static function main() { $commonIn = new CommonInParam(); $commonIn->setUserId(0); $commonIn->setAppId(1); $commonIn->setAreaId(10); $commonIn->setServerIp('127.0.0.1'); $commonIn->setUserIp(''); $query = new QueryParam(); $query->setActivityId(123); $query->setPage(1); $query->setSize(10); $query->setOrderType(1); $request = new GetRequest(); $request->setInParam($commonIn); $request->setQueryParam($query); $requestBuf = $request->serializeToString(); $packBuf = pack('CN', 0, strlen($requestBuf)) . $requestBuf; go(function () use ($packBuf){ $path = "/protocol.QD.ActCommentServer.CommentObj/getComment"; $ret = self::callGrpc('127.0.0.1', 10008, $path, $packBuf); //這裏注意要修改爲你服務在tars上綁定的ip 127.0.0.1不必定能夠 $response = new GetResponse(); $response->mergeFromString(substr($ret, 5)); foreach ($response->getList() as $row) { var_dump($row->getContent()); } }); } }
執行php client.php觀察返回。
前面提到的client,只是咱們訪問PB server 的簡單demo,能夠幫助咱們測試PB server的狀態。若是須要在其餘Tars服務中調用PB server應該如何使用呢?和Tars相似咱們也提供了生成PB client端代碼的方式。
這裏使用TarsActDemo下的QD.ActHttpServer爲範例演示如何生成Tars PB client代碼並調用PB服務。
範例以下:
$inParam = new CountRequest(); $outParam = new CountResponse(); $conf = self::getConfig(); $conf->setSocketMode(4); $servant = new CommentObjServant($conf); $servant->getCommentCount($inParam, $outParam); return $outParam->getCount();
TarsGo中關於PB的支持,本質是對proto協議文件的支持,提供將proto協議文件轉換爲tars協議的能力,在相互調用中實際使用的是tars協議。這個服務能夠和其餘Tars服務相互工做。
TarsPHP中關於PB的支持,是構建了一個gRPC服務,這個服務部署在Tars平臺上,參與Tars平臺尋址,受Tars平臺管理。這個服務使用gRPC on Http2做爲網絡通信協議,使用Protobuf做爲編碼協議,能夠和其餘PB client 相互工做。
二者方向不一樣,不能混合使用,但願你們區分。
咱們使用相同Http服務,分別使用Tars和Pb協議和後端服務通信並進行壓測。
服務器環境:2核 4G,php 7.2.16,swoole 4.4.0
服務空跑指的是簡單的ping到後端服務,不進行任何業務處理直接返回;
單次簡單RPC指的是向後端服務獲取彈幕數量返回一個int,數量值rand生成,並無使用mysql count;
單次複雜PRC會實際向後端獲取彈幕列表結構體,包含多條彈幕對象完整結構。
從壓測數據來看,Tars性能比PB高出一截,但對比二者打包解包性能發現PB打包解包性能略優於Tars,致使這樣結果的主要緣由我認爲是gRPC使用Http2做爲通信協議相比Tars的自定義通信協議須要更多開銷。
TarsPHP項目源碼地址:https://github.com/TarsPHP/Ta...
TARS全部版本源碼地址:https://github.com/TarsCloud
(喜歡的話記得給項目點個star哦~!)
TARS-PHP QQ交流羣: 7695317344