所谓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目录
4.查看是否成功
二、使用protoc安装 proto文件生成php代码
1.把生成的proto文件放在当前项目的目录下,如下图的1标记所示:
2.用protoc命令生成proto文件为php代码
protoc --php_out=. public.proto
protoc --php_out=. dydb_guide.proto
通过以上命令生成上图所示的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