TarsPHP New Version Released, Supports Protobuf Protocol
Tars
Published at 08/07/2019
News
Views 2928

Tars is a microservices development framework that Tencent has been using from 2008 to today. It became an open source project of the Linux Foundation in 2018 and currently supports C ++, Java, PHP, NodeJS, and Go languages. This framework provides users with a complete set of solutions related to development, operation and maintenance, and testing, helping a product or service to be rapidly developed, deployed, tested, and launched. It integrates extensible protocol codec, high-performance RPC communication framework, name routing and discovery, release monitoring, log statistics, and configuration management. It can quickly build its own stable and reliable distributed applications using microservices, and Achieve complete and effective service governance.

TarsPHP, as a solution for Tars in the PHP language , is designed with the following four aspects in mind:

  • Complete functions : benchmark existing C ++, Java and NodeJS system functions
  • Flexible : On flexible, who is competing with PHP?
  • Lightweight : With the lightest design, click to stop, plug and play
  • Efficient : Plug in the wings of the Swoole coroutine and have to fly

Protobuf Introduction

Protocol buffers (abbreviated as PB) is Google's open source language-neutral, platform-independent, extensible serialized data format that can be used for communication protocols, data storage, etc. It's similar to XML, but smaller, faster, and simpler than XML.

PB is a coding protocol. If network transmission and RPC calls are involved, a communication protocol needs to be introduced. Google's open source RPC framework gRPC uses Http2 as the communication protocol and PB as the encoding protocol.

Build PB Server with TarsPHP

Initialize the environment
Protoc installation

First you need to install the protoc library. The main role of this library is to package and unpack the protobuf protocol data. You can refer to https://github.com/protocolbuffers/protobuf/tree/master/src to install directly.

./autogen.sh
./configure
make
make install

If protoc -version can output normally, the installation is complete

php protobuf installation

After that, you need to install the php protobuf extension. This extension is mainly used as a bridge between the php and protoc libraries.

git clone https://github.com/protocolbuffers/protobuf.git
cd ./php/ext/google/protobuf/
phpize
./configure
make
make install
(Need to edit `php.ini`,open protobuf extension)

If php -ri protobuf has output, the installation is normal.

Swoole installation

It is recommended to use 4.4.0 or above. You need to enable http2 and openssl support.

Write a proto file

Referring to the tars file of the comment service in ActDemo in TarsPHP, we wrote a protocol file for actComment.proto.

Unlike the tars protocol file, the proto protocol stipulates that the input and output parameters must and can only be a message structure, so the input and output parameters need to be encapsulated in a single message.

syntax = "proto3";  

package protocol.QD.ActCommentPbServer; 

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;   
};  

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;  
};
Generate server-side code

Protoc can generate the corresponding PHP class code according to the proto file, but the official does not support proto files to generate server-side code. You can use the gRPC plugin to generate client code. If you need to use the generated client code, we also need to install the grpc library and grpc php extension.

Therefore, our idea is to first use protoc to generate the classes required by PHP, and then parse the proto file to generate the server-side interface. This process is very similar to the existing tars2php process, so we call it proto2php.

Because it is more trouble to use two tools to generate, we integrate the process of calling proto into proto2php for your convenience.

We first build a tars.proto.php to set up some basic information.

return array(
    'appName' => 'QD',
    'serverName' => 'ActCommentPbServer',
    'objName' => 'CommentObj',
    'withServant' => true, 
    'tarsFiles' => array(
        './actComment.proto',
    ),
    'dstPath' => '../src/protocol', 
    'protocDstPath' => '../src', 
    'namespacePrefix' => 'Protocol',
);

Then execute php… / src / vendor / phptars / tars2php / src / proto2php.php ./tars.proto.php
to generate the GPBMetadata directory and the protocol directory. Among them, protocol is the php class generated by the proto file, and CommentObjServant.php is the server-side interface class generated by the proto2php file. You need to implement this class to build TarsPHP pb server.

Deploy TarsPHP PB server

Follow the Readme in the Demo to deploy the tarsphp pb server.

A few notes:

  1. The interface logic needs to be implemented in the impl directory.

  2. Specify home-api, home-class location in services.php under src, protocolName is pb, serverType is grpc

  3. The protocol type on the tars platform is tcp, a non-tars protocol.

  4. You need to add require “google / protobuf” in composer.json, and you need to configure Protocol and GPBMetadata in autoload. Examples are as follows:

     {
         "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"
         }
     }
    

Finally, execute composer run-script deploy to generate a code package and upload it to the Tars platform for distribution.

Use client access

You can use the php client generated by gRPC to access the test, or you can directly use swoole's http2 client to build a grpc 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); 
            $response = new GetResponse();
            $response->mergeFromString(substr($ret, 5));
            foreach ($response->getList() as $row) {
                var_dump($row->getContent());
            }
        });
    }
}

Run php client.php and observe the return.

Generate client-side code

The client mentioned earlier is just a simple demo of our access to the PB server, which can help us test the status of the PB server. How to use PB server if it needs to be called in other Tars services? Similar to Tars, we also provide a way to generate PB client code.

Here, QD.ActHttpServer under TarsActDemo is used as an example to demonstrate how to generate Tars PB client code and call the PB service.

  1. Copy the actComment.proto file to the tars directory
  2. Build the actCommentPb.proto.php file with the same content as the tars.proto.php used to generate the server code. Modify withServant = false
  3. Execute php ... / src / vendor / phptars / tars2php / src / proto2php.php ./actCommentPb.proto.php
  4. You can see the relevant generated code in protocol / QD / ActCommentPbServer. (Similar to the server code, CommentObjServant.php is generated by proto2php, and other files are generated by proto2php calling the protoc plugin)
  5. Similar to the server side, you need to add GPBMetadata and Protocol to psr-4 in composer.json.
  6. Similar to the Tars call, you can directly call the related methods of the CommentObjServant class to communicate with the PB service. Note that the socketModel in the CommunicatorConfig needs to be set to 4 grpc mode.

Examples are as follows:

$inParam = new CountRequest();  
$outParam = new CountResponse();  

$conf = self::getConfig();  
$conf->setSocketMode(4);  

$servant = new CommentObjServant($conf);  
$servant->getCommentCount($inParam, $outParam);  

return $outParam->getCount();
Difference from TarsGo regarding PB support

The support for PB in TarsGo is essentially support for the proto protocol file, providing the ability to convert the proto protocol file to the tars protocol. The tars protocol is actually used in mutual calls. This service can work with other Tars services.

TarsPHP's support for PB is to build a gRPC service , which is deployed on the Tars platform, participates in the Tars platform addressing, and is managed by the Tars platform. This service uses gRPC on Http2 as the network communication protocol and Protobuf as the encoding protocol, and can work with other PB clients.

The two directions are different and cannot be mixed . I hope everyone will distinguish.

related data

We use the same Http service, and use the Tars and Pb protocols to communicate with the back-end service and perform stress testing.

  • Server environment: 2 core 4G, php 7.2.16, swoole 4.4.0
  • Service dry running refers to a simple ping to the back-end service, and returns directly without any business processing;
  • A single simple RPC refers to obtaining the number of barrage from the back-end service and returning an int, the number value is generated by rand, and mysql count is not used;
  • A single complex PRC will actually obtain a barrage list structure from the back end, including the complete structure of multiple barrage objects.
QDPSPBTARS
Service Run38006200
Single Simple RPC36006150
Single Complex RPC10501150

From the pressure test data, the performance of Tars is a bit higher than that of PB, but comparing the performance of packaging and unpacking of PB, it is found that the performance of PB packaging and unpacking is slightly better than Tars . It requires more overhead than Tars' custom communication protocol.

Welcome to the project site star and contribute.

https://github.com/TarsPHP/TarsPHP
https://github.com/TarsCloud/Tars