php使用grpc(windows环境下)

所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样

比如:服务器端实现一个服务(Go语言实现),客户端用php调用,最终效果象调用本地方法一样使用。

一、下载Protoc
下载地址:https://github.com/protocolbuffers/protobuf/releases/download/v3.7.1/protoc-3.7.1-win64.zip,此软件是用于把proto文件生成Php端的代码
操作步骤:
1.解压
2.把protoc-3.7.1的文件夹放到c盘下的 program files文件夹下面
3.右击 "计算机",属性->高级->环境变量,在系统变量的path中追加protoc的bin目录
php使用grpc(windows环境下)

4.查看是否成功
php使用grpc(windows环境下)

 

二、使用protoc安装 proto文件生成php代码
1.把生成的proto文件放在当前项目的目录下,如下图的1标记所示:
php使用grpc(windows环境下)

2.用protoc命令生成proto文件为php代码
protoc --php_out=. public.proto
protoc --php_out=. dydb_guide.proto

php使用grpc(windows环境下)
通过以上命令生成上图所示的2对应的目录

public.proto的文件内容如下所示:
 

syntax = "proto3";

package public;

option go_package = ".;dydbpb";

enum DBType {
    mongodb = 0; 
    mysql = 1;
    postgresql = 2;
} // 暂时只支持mongodb

message Project {
    string project_id = 2; // 必须,项目id,可对应合同
    string project_type = 1; // 可选,项目类型,按类型设置namespace,不设置时默认为公共空间public
    DBType database_type = 3; // 可选,首次创建不指定时默认为mongodb,或根据database_id匹配
    string database_id = 4;// 可选, 数据库id,不指定时默认为"project_type-project_id",多个数据库时可指定
    string capacity =5;// 可选, 数据库初始容量
    string copy_database=6; // 可选,默认为空忽略,设置为已有数据库的database_id则拷贝已有数据库磁盘建立新库
}

message Database {
    // Project project=1;
    string name = 1;
    string namespace=2;
    string database_id =3;
    string type = 4;
    string version =5;
    string user =6;
    string password = 7;
    string url = 8;
    bool new_disk = 9;
    string pvc_id = 10;
    string capacity =11;
}

// 是否成功
message Success {
    bool ok = 1;
    string reason = 2;
}

dydb_guide文件内容
 

syntax = "proto3";

package dydbguide;

option go_package = ".;dydbpb";

import "public.proto";


service DydbGuide {
    // GetDB 启动数据库服务并返回数据库地址
    rpc GetDB(public.Project) returns (public.Database) {}
    // NewDB 放弃原数据库磁盘,创建新磁盘(下次启动生效)
    rpc NewDB(public.Project) returns (public.Success) {}
    // KeepAlive 保持开启,用于有对应流程在运行
    rpc KeepAlive(public.Project) returns (public.Success) {}
    // DBStatu 查询数据库当前状态
    rpc GetDBStatu(public.Project) returns (Status) {}
    // DBInfo 查询数据库当前统计,如空间大小, 类型, 密码,已使用空间大小,记录数,最大资源使用,启动次数,启动总时长,最近启动时间,最近关闭时间,最近访问时间,请求次数(总/最近),磁盘列表等
    rpc GetDBInfo(public.Project) returns (Info) {}
}

// 流程状态信息
message Status {
    enum Statu {
        // 准备中
        pending = 0; 
        // 运行中
        running = 1;
        // 失败出错
        failed = 2;
        // 关闭冻结
        closed = 3;
    }
    Statu statu = 1;
    public.Database database = 2;
    bytes message = 3;
}

// 信息
message Info {
    public.Database database = 1;
    string create_time = 2;
    string latest_start_time = 3;
    string latest_close_time = 4;
    string latest_visit_time = 5;
    int32 sum_work_time = 6;
    int32 sum_start_num =7;
    int32 sum_visit_num = 8;
    string capacity = 9; 
    string used_size = 10;
}

 

二、使用composer安装php组件
1.在composer.json中追加如下信息,require信息标识要用的新组件,autoload标识要加入命名空间

{
  "require": {
    "google/protobuf": "^3.17",
    "grpc/grpc": "^1.38"
  },
  "autoload":{
    "psr-4":{
      "GPBMetadata\\":"GPBMetadata/",
      "PBPublic\\":"PBPublic/",
      "Dydbguide\\":"Dydbguide/"
    }
  }
}

2.执行composer update命令
通过update方法后,就可以通过命名空间直接调用到Dydbguide和PBPublic对应的代码
 

 

三、在已生成的代码目录下添加入口文件
1.在Dydbguide文件夹下增加DydbguideClient.php

<?php
namespace Dydbguide;

/**
 * service Dydbguide{}
 * 编写 (gprc 定义 Dydbguide 服务)的客户端
 */
class DydbguideClient extends \Grpc\BaseStub
{

    public function __construct($hostname, $opt_params = null, $channel = null) 
    {
        try {
            $opts = [
                'credentials' => \Grpc\ChannelCredentials::createInsecure(),
                'timeout' => 1,
            ];
            if (!empty($opt_params)) {
                $opts = array_merge($opts, $opt_params);
            }
            
            parent::__construct($hostname, $opts, $channel);
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
    }

    /**
     * 获取数据库,如果不存在则创建新的数据库
     *
     *
     **/
    public function getDB($params)
    {
        try {
            $verify = new \Custom\Org\Verify;

            $verify->required($params, ['project_sn']);

            $request = new \PBPublic\Project();
            $request->setProjectId($params['project_sn']);
            if (isset($params['project_type'])) {
                $request->setProjectType($params['project_type']);
            }
            $result = $this->_getDB($request)->wait();

            list($obj, $reply) = $result;

            $response = [];
            if ($reply->code == 0) {

                $response['name']      = $obj->getName();
                $response['namespace'] = $obj->getNamespace();
                $response['db_id']     = $obj->getDatabaseId();
                $response['type']      = $obj->getType();
                $response['version']   = $obj->getVersion();
                $response['user']      = $obj->getUser();
                $response['password']  = $obj->getPassword();
                $response['url']       = $obj->getUrl();
                $response['new_disk']  = $obj->getNewDisk();
                $response['pcv_id']    = $obj->getPvcId();
                $response['capacity']  = $obj->getCapacity();
            }

            return $response;
        } catch (\Exception $e) {
            throw new \Exception ($e->getMessage());
        }
    }

    /**
     * 获取数据库,如果不存在则创建新的数据库
     *
     * 该方法的参数是按照proto的文件来编写的
     **/
    private function _getDB(\PBPublic\Project $argument, $metadata=[], $options=[]){
        try {
        
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
        return $this->_simpleRequest('/dydbguide.DydbGuide/GetDB', $argument,['\PBPublic\Database', 'decode'], $metadata, $options);
    }



    /**
     * 已有的项目创建新的数据库(当前用不上)
     *
     *
     **/
    public function newDB(\PBPublic\Project $params){

       
        $result = $this->_newDB($params)->wait();

        list($obj, $reply) = $result;
        if ($reply->code == 0) {
            
        }
    }

    /**
     * 已有的项目创建新的数据库(当前用不上)
     *
     *该方法的参数是按照proto的文件来编写的
     **/
    private function _newDB(\PBPublic\Project $argument, $metadata=[], $options=[]){
        return $this->_simpleRequest('/dydbguide.DydbGuide/NewDB', $argument,['\PBPublic\Success', 'decode'], $metadata, $options);
    }

}

四、测试php端代码
 

public function test()
    {
        set_time_limit(0);
        $ip = 'ip地址:端口号';
        $api = new \Dydbguide\DydbguideClient($ip);

        $result = $api->getDb(['project_sn' => 'zytest0524', 'project_type' => 'ygdd']);
        print($result);
        
    }

结果为:
 

Array
(
    [name] => dydb-zytest0524
    [namespace] => dydb-ygdd
    [db_id] => zytest0524
    [type] => mongodb
    [version] => 
    [user] => admin
    [password] => BNPA0TPM
    [url] => 10.11.0.210:27017
    [new_disk] => 
    [pcv_id] => dydb-zytest0524-pvc-1621912935241594000
    [capacity] => 10Gi
)

 

 

参考链接:https://blog.csdn.net/uisoul/article/details/90483050

 
上一篇:go-php-grpc-example


下一篇:GRPC生成各语言语句收集