TarsPHP发布新版,支持Protobuf协议
Posted OSC开源社区
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TarsPHP发布新版,支持Protobuf协议相关的知识,希望对你有一定的参考价值。
功能完善:对标现有C++、Java与NodeJS体系功能
灵活:论灵活,谁与PHP争锋?
轻量:用最轻量的设计,点到即止,即插即用
高效:插上Swoole协程的翅膀,不得不飞
Protobuf简介
Protocol buffers (简称PB)是Google开源的语言中立,平台无关,可扩展的序列化数据的格式,可用于通信协议,数据存储等。它和XML类似,但比XML更小,更快,更简单。
PB是编码协议,如果涉及到网络传输和RPC调用,就需要引入通讯协议。Google开源的RPC框架gRPC就使用Http2作为通讯协议,PB作为编码协议。
使用TarsPHP 构建 PB Server
初始化环境
Protoc 安装
-
首先需要安装protoc库,这个库的主要作用是打包解包protobuf协议数据。 可以参考
https://github.com/protocolbuffers/protobuf/tree/master/src直接安装。./autogen.sh
./configure
make
make install如果 protoc –version 可以正常输出,说明安装完成 -
php protobuf安装 -
之后需要安装 php protobuf扩展,这个扩展主要用作php和protoc库中间的一个桥梁。 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支持。
编写一个proto文件
参考TarsPHP中ActDemo中评论服务的tars文件,我们写了一个actComment.proto的协议文件。
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;
};
生成server端代码
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需要实现这个类。
部署TarsPHP PB server
按照Demo中 Readme部署tarsphp pb server即可。
需要在impl目录中实现interface逻辑。
在src下的services.php中指定home-api,home-class位置,protocolName是pb,serverType是grpc
tars平台上协议类型是 tcp,非tars协议。
-
需要在composer.json中添加require “google/protobuf”,autoload中需要配置 Protocol 和 GPBMetadata,范例如下: {
"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平台上发布。
使用client访问
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端代码
前面提到的client,只是我们访问PB server 的简单demo,可以帮助我们测试PB server的状态。如果需要在其他Tars服务中调用PB server应该如何使用呢?和Tars类似我们也提供了生成PB client端代码的方式。
拷贝actComment.proto文件到tars目录
构建actCommentPb.proto.php 文件,内容和生成server代码用的tars.proto.php内容一致,修改 withServant = false
执行
php…/src/vendor/phptars/tars2php/src/proto2php.php ./actCommentPb.proto.php之后在protocol/QD/ActCommentPbServer 中可以看到相关生成代码。(和Server 端代码类似,CommentObjServant.php是 proto2php生成的,其他文件是proto2php 调用 protoc 插件生成的)
和Server端类似需要添加 GPBMetadata 和 Protocol 到composer.json 的psr-4中。
和Tars 调用类似,可以直接调用CommentObjServant类的相关方法和PB 服务通讯。需要注意的是 传入的 CommunicatorConfig 中的socketModel 需要设置为 4 grpc 模式。
$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支持的不同
TarsGo中关于PB的支持,本质是对proto协议文件的支持,提供将proto协议文件转换为tars协议的能力,在相互调用中实际使用的是tars协议。这个服务可以和其他Tars服务相互工作。
TarsPHP中关于PB的支持,是构建了一个gRPC服务,这个服务部署在Tars平台上,参与Tars平台寻址,受Tars平台管理。这个服务使用gRPC on Http2作为网络通讯协议,使用Protobuf作为编码协议,可以和其他PB client 相互工作。
两者方向不同,不能混合使用,希望大家区分。
相关数据
服务器环境:2核 4G,php 7.2.16,swoole 4.4.0
服务空跑指的是简单的ping到后端服务,不进行任何业务处理直接返回;
单次简单RPC指的是向后端服务获取弹幕数量返回一个int,数量值rand生成,并没有使用mysql count;
-
单次复杂PRC会实际向后端获取弹幕列表结构体,包含多条弹幕对象完整结构。
从压测数据来看,Tars性能比PB高出一截,但对比两者打包解包性能发现PB打包解包性能略优于Tars,导致这样结果的主要原因我认为是gRPC使用Http2作为通讯协议相比Tars的自定义通讯协议需要更多开销。
欢迎给项目点 star 并参与贡献。
https://github.com/ TarsCloud/Tars
开源中国征稿啦!
开源中国 www.oschina.net 是目前备受关注、具有强大影响力的开源技术社区,拥有超过 400 万的开源技术精英。我们传播开源的理念,推广开源项目,为 IT 开发者提供一个发现、使用、并交流开源技术的平台。
现在我们开始对外征稿啦!如果你有优秀的技术文章想要分享,热点的行业资讯需要报道等等,欢迎联系开源中国进行投稿。投稿详情及联系方式请参见:
以上是关于TarsPHP发布新版,支持Protobuf协议的主要内容,如果未能解决你的问题,请参考以下文章
TarsGo新版本发布,支持protobuf,zipkin和自定义插件