php中使用protobuffer

37次阅读

共计 2823 个字符,预计需要花费 8 分钟才能阅读完成。

Protobuf 简介

protobuf(Protocol buffers)是谷歌出品的跨平台、跨语言、可扩展的数据传输及存储的协议,是高效的数据压缩编码方式之一。

Protocol buffers 在序列化数据方面,它是灵活的,高效的。相比于 XML 来说,Protocol buffers 更加小巧,更加快速,更加简单。一旦定义了要处理的数据的数据结构之后,就可以利用 Protocol buffers 的代码生成工具生成相关的代码。甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。

Protocol buffers 很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

此外,Protobuf 由于其在内网高效的数据交换效率,是被广泛应用于微服务的,在谷歌的开源框架 grpc 即是基于此构建起来的。

php-protobuf 安装

由于 protobuf 原生并不支持 php,所以 php 如果使用 pb 则需要安装相应扩展。

pecl install protobuf

环境中需要有 protoc 编译器,下载安装方式:

$ wget https://github.com/google/protobuf/releases/download/v2.5.0/protobuf-2.5.0.tar.gz
$ tar zxvf protobuf-2.5.0.tar.gz
$ cd protobuf-2.5.0
$ ./configure --prefix=/usr/local/protobuf
$ sudo make 
$ sudo  make install

验证安装成功:

$ /usr/local/protobuf/bin/protoc  --version
libprotoc 2.5.0

php-protobuf 安装成功

php --ri protobuf

安装 lumen 和 google/protobuf 依赖

lumen new rpc

lumen new rpc命令相当于composer create-project laravel/lumen rpc

composer require google/protobuf

composer.json 下添加 classmap:

{
    "classmap": ["protobuf/"]
}

ok,准备工作都已做好了。

自己做一个 demo

在代码目录下创建一个 protobuf 文件夹mkdir protobuf

进入该目录,创建一个文件searchRequest.proto

syntax = "proto3";
message SearchRequest {
    string query = 1;
    int32 page_number = 2;
    int32 result_per_page = 3;
    enum Corpus {
        UNIVERSAL = 0;
        WEB = 1;
        IMAGES = 2;
        LOCAL = 3;
        NEWS = 4;
        PRODUCTS = 5;
        VIDEO = 6;
    }
    Corpus corpus = 4;
}

???? 此处很重要????

composer.json 下添加 classmap,否则将无法侦测到对应 class

{
   "classmap": ["protobuf/"]
}

在命令行下运行:protoc --proto_path=protobuf/ --php_out=protobuf/ protobuf/searchRequest.proto && composer dump-autoload

现在你看到的代码目录,应该是这样的:

现在,我们需要的请求类已经得到了,现在看看如何使用它!

使用

在 web.php 创建一个路由

$router->get('testp', 'ExampleController@testProtobuf');

ExampleController 下添加:

    public function testProtobuf()
    {// require_once base_path('protobuf/SearchRequest.php');
        $request = new \SearchRequest();
        $request->setPageNumber(67);
        dd($request->getPageNumber());
    }

如果正常打印出 67 这个数字,就表示该类可以用,恭喜你已经成功完成了一个请求类的创建。

Go deeper

现在,看一下生成的 SearchRequest 都有哪些方法:

array:16 [▼
  0 => "__construct"
  1 => "getQuery"
  2 => "setQuery"
  3 => "getPageNumber"
  4 => "setPageNumber"
  5 => "getResultPerPage"
  6 => "setResultPerPage"
  7 => "getCorpus"
  8 => "setCorpus"
  9 => "clear"
  10 => "discardUnknownFields"
  11 => "serializeToString"
  12 => "mergeFromString"
  13 => "serializeToJsonString"
  14 => "mergeFromJsonString"
  15 => "mergeFrom"
]

这里面带有 set 前缀的方法,都是设定对应字段的,带有 get 的,都是从 buffer 中获取值的,里面的 SerializeToString,建议阅读官方文档,里面有对应的合理的解释。

和 grpc 的结合

composer install grpc/grpc

定义 Service,这一个需要在 client 和 server 两端都要完成

service RouteGuide {rpc GetFeature(Point) returns (Feature) {}
   rpc RecordRoute(stream Point) returns (RouteSummary) {}
   rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}}

message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}

protoc生成对应的 Service 实例。

创建一个 client

$client = new Routeguide\RouteGuideClient('localhost:50051', ['credentials' => Grpc\ChannelCredentials::createInsecure(),
]);

调用 RPC 服务

$point = new Routeguide\Point();
$point->setLatitude(409146138);
$point->setLongitude(-746188906);
list($feature, $status) = $client->GetFeature($point)->wait();

grpc 更多实现,请参阅官方文档、快速指南

正文完
 0