PHP使用GRPC

  • 前言
  • 下载Protoc
  • 编写proto文件
  • 代码实现
    • 准备
    • 服务端服务实现
    • 客户端请求实现

前言

在上节已经介绍了GRPC,不了解GRPC的可以先看下。
本文将讲述PHP如何使用GRPC

下载Protoc

上节讲了GPRC使用协议缓冲区,需要使用protoc特殊的 gRPC 插件从您的 proto 文件生成代码。
点击 下载地址 选择对应的平台。
我本机是windows10 x64,对应的下载链接

将下载的压缩包解压,bin文件路径加入到系统环境变量Path中
打开命令行运行

protoc --version

查看protoc版本是否运行成功

编写proto文件

万事开头say hello,下面写一个helloworld.proto。proto3语言指南

// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.syntax = "proto3";option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";package helloworld;// The greeting service definition.
// 定义服务
service Greeter {// Sends a greeting// 服务接口 // HelloRequest请求体// HelloReply 响应体rpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the user's name.
// 定义请求参数
message HelloRequest {string name = 1;
}// The response message containing the greetings
// 定义响应数据
message HelloReply {string message = 1;
}

打开命令行窗口,使用protoc工具生成客户端代码和服务端代码

protoc --php_out=php   ./helloworld.proto
# --php_out : 指定php输出路径

执行以上命令后
会再php文件夹目录下生成以下文件

主要看Helloworld文件夹下的文件
响应类HelloReply.php

namespace Helloworld;use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;/*** The response message containing the greetings** Generated from protobuf message <code>helloworld.HelloReply</code>*/
class HelloReply extends \Google\Protobuf\Internal\Message
{/*** protoc文件定义Reply的属性Message* Generated from protobuf field <code>string message = 1;</code>*/protected $message = '';/*** Constructor.** @param array $data {*     Optional. Data for populating the Message object.**     @type string $message* }*/public function __construct($data = NULL) {\GPBMetadata\Examples\Protos\Helloworld::initOnce();parent::__construct($data);}/*** 获取响应数据,在客户端实现获取* Generated from protobuf field <code>string message = 1;</code>* @return string*/public function getMessage(){return $this->message;}/*** 响应数据赋值,在服务端实现赋值* Generated from protobuf field <code>string message = 1;</code>* @param string $var* @return $this*/public function setMessage($var){GPBUtil::checkString($var, True);$this->message = $var;return $this;}}

请求类HelloRequest.php

namespace Helloworld;use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;/*** The request message containing the user's name.** Generated from protobuf message <code>helloworld.HelloRequest</code>*/
class HelloRequest extends \Google\Protobuf\Internal\Message
{/*** Generated from protobuf field <code>string name = 1;</code>*/protected $name = '';/*** Constructor.** @param array $data {*     Optional. Data for populating the Message object.**     @type string $name* }*/public function __construct($data = NULL) {\GPBMetadata\Helloworld::initOnce();parent::__construct($data);}/*** 从protobuf字段生成string name = 1* Generated from protobuf field <code>string name = 1;</code>* @return string*/public function getName(){return $this->name;}/*** 从protobuf字段生成string name = 1* Generated from protobuf field <code>string name = 1;</code>* @param string $var* @return $this*/public function setName($var){GPBUtil::checkString($var, True);$this->name = $var;return $this;}}

我们在新建个客户端类,作为客户端连接的模板,后面实现时继承该类
HelloClient.php

<?php
/*** Created by PhpStorm.* User: 17208* Date: 2021/7/22* Time: 13:50*/namespace Helloworld;/*** The greeting service definition.*/
class HelloClient extends \Grpc\BaseStub {/*** @param string $hostname hostname* @param array $opts channel options* @param \Grpc\Channel $channel (optional) re-use channel object*/public function __construct($hostname, $opts, $channel = null) {parent::__construct($hostname, $opts, $channel);}/*** 这里对应protobuf定义的服务* @param \Helloworld\HelloRequest $argument input argument* @param array $metadata metadata* @param array $options call options* @return \Grpc\UnaryCall*/public function SayHello(\Helloworld\HelloRequest $argument, $metadata = [], $options = []) {return $this->_simpleRequest('/helloworld.Greeter/SayHello',$argument,['\Helloworld\HelloReply', 'decode'],$metadata, $options);}
}

再新建个服务类,作为服务模板继承,用于开启服务
HelloStub.php


namespace Helloworld;namespace Helloworld;/*** The greeting service definition.*/
class HelloStub {/*** 这里对应protobuf定义的服务* Sends a greeting* @param \Helloworld\HelloRequest $request client request* @param \Grpc\ServerContext $context server request context* @return \Helloworld\HelloReply for response data, null if if error occured*     initial metadata (if any) and status (if not ok) should be set to $context*/public function SayHello(\Helloworld\HelloRequest $request,\Grpc\ServerContext $context): ?\Helloworld\HelloReply {$context->setStatus(\Grpc\Status::unimplemented());return null;}/*** Get the method descriptors of the service for server registration** @return array of \Grpc\MethodDescriptor for the service methods*/public final function getMethodDescriptors(): array{return ['/helloworld.Greeter/SayHello' => new \Grpc\MethodDescriptor($this,'SayHello','\Helloworld\HelloRequest',\Grpc\MethodDescriptor::UNARY_CALL),];}}

代码实现

准备

1.下载安装 PHP的gRPC扩展和protobuf扩展
2.安装 composer 来管理和加载PHP的类库
composer.json

{"name": "grpc-go-php","require": {"grpc/grpc": "^v1.3.0","google/protobuf": "^v3.3.0"},"autoload":{"psr-4":{"GPBMetadata\\":"GPBMetadata/","Helloworld\\":"Helloworld/"}}
}

运行composer install 加载类库

composer install

服务端服务实现

新建文件 server.php

// 引入类库
require dirname(__FILE__) . '/vendor/autoload.php';// 定义服务类继承Helloworld\GreeterStub
class Greeter extends Helloworld\GreeterStub
{// 实现接口public function SayHello(\Helloworld\HelloRequest $request,\Grpc\ServerContext $serverContext):? \Helloworld\HelloReply {// 获取请求参数$name = $request->getName();// 定义一个实例响应体$response = new \Helloworld\HelloReply();// 服务逻辑实现$msg = "Hello ".$name;// 响应体返回$response->setMessage($msg);return $response;}
}
// 初始化并启动服务
$server = new \Grpc\RpcServer();
$server->addHttp2Port('0.0.0.0:50052');// 定义服务端口
$server->handle(new Greeter());
$server->run();

运行

php server.php

运行效果

客户端请求实现

新建文件 client.php

// 引入类库
require dirname(__FILE__).'/vendor/autoload.php';function greet($hostname, $name)
{// 初始化一个客户端实例$client = new Helloworld\GreeterClient($hostname, ['credentials' => Grpc\ChannelCredentials::createInsecure(),]);// 初始化一个请求类$request = new Helloworld\HelloRequest();// 参数赋值$request->setName($name);// 请求服务list($response, $status) = $client->SayHello($request)->wait();// 响应处理if ($status->code !== Grpc\STATUS_OK) {echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;exit(1);}echo $response->getMessage() . PHP_EOL;
}$name = !empty($argv[1]) ? $argv[1] : 'world';
$hostname = !empty($argv[2]) ? $argv[2] : 'localhost:50052';
greet($hostname, $name);

在当前文件夹打开命令行窗口运行

php client.php

运行结果:

gRPC(2)- PHP使用gRPC相关推荐

  1. undefined: grpc.SupportPackageIsVersion6 和 undefined: grpc.ClientConnInterface 解决办法

    问题表现 编译protobuf的 .pb.go文件时报错,如 undefined: grpc.SupportPackageIsVersion6 或 undefined: grpc.ClientConn ...

  2. PICE(6):集群环境里多异类端点gRPC Streaming - Heterogeneous multi-endpoints gRPC streaming

    gRPC Streaming的操作对象由服务端和客户端组成.在一个包含了多个不同服务的集群环境中可能需要从一个服务里调用另一个服务端提供的服务.这时调用服务端又成为了提供服务端的客户端了(服务消费端) ...

  3. PICE(6):集群环境里多异类端点gRPC Streaming - Heterogeneous multi-endpoints gRPC streaming...

    gRPC Streaming的操作对象由服务端和客户端组成.在一个包含了多个不同服务的集群环境中可能需要从一个服务里调用另一个服务端提供的服务.这时调用服务端又成为了提供服务端的客户端了(服务消费端) ...

  4. gRPC(1)- gRPC 简介

    概述 在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,使您可以更轻松地创建分布式应用程序和服务.与许多 RPC 系统一样,gRPC 基于定义服务的 ...

  5. grpc使用记录(一) gRPC编译(mscv/gcc)

    目录 1.编译前的准备工作 2.Windows下使用VS2019编译 2.1.使用cmake生成VS2019解决方案 2.2.使用msbuild工具进行编译 3.linux下编译 3.1 CentO ...

  6. php yat grpc,Laravel 5 使用 Grpc 构建的微服务

    最近有用微服务相关的项目,所以记录一下. 服务端采用的是 NodeJS 代码就不贴了(主要是计算DY签名的),这里贴一下 .proto 文件的代码 proto 文件 syntax = "pr ...

  7. python grpc 并发_python中grpc的使用示例

    本文介绍了在Python中使用gRPC的方法示例, 具体如下: 使用 Protocol Buffers的跨平台RPC系统. 安装 使用 pip pip installgrpcio pipinstall ...

  8. .net core 下的 grpc网关——http到grpc的网关源码剖析

    我曾经有段时间,特别想写一款从Http的json请求到grpc协议的网关,以便顺应asp.net core3.1的grpc微服务支持,grpc虽然从性能上稍微逊色于其他基于tcp的rpc,但由于是微软 ...

  9. grpc调用_使用gRPC和协议缓冲区实现远程过程调用

    grpc调用 RPC简介 ( Introduction To RPC ) Remote procedure call (RPC) architecture is popular in building ...

  10. SpringBoot整合Grpc实现跨语言RPC通讯

    什么是gRPC gRPC是谷歌开源的基于go语言的一个现代的开源高性能RPC框架,可以在任何环境中运行.它可以有效地连接数据中心内和跨数据中心的服务,并提供可插拔的支持,以实现负载平衡,跟踪,健康检查 ...

最新文章

  1. php多选框怎么传值,tp3.2如何处理多选框传参和判断状态
  2. 怎么把本地的文件传给服务器,怎么把本地文件传给云服务器
  3. 理解单片机系统—汇编语言
  4. 树的遍历-Preorde Traversal,Inorder Traversal,Postoder Traversal
  5. 【计算机组成原理】英文选择题题库
  6. ​【月报】Java知音的三月汇总
  7. 从客户端中(...)检测到有潜在危险的 Request.Form值
  8. linux删除文件密码不奏效,Linux运维知识之linux_无秘登录问题(不生效)
  9. Hadoop开发环境准备及错误问题解决方法
  10. 【第七课】Smart 3D集群教程
  11. SpringBoot - 自动装配 源码解析
  12. 第二十章 齐桓公大婚冤家又聚首 宋闵公嘲笑重臣丢君命(
  13. Appium + IOS 自动化环境搭建教程(实践+总结+踩坑)
  14. 剑指offer算法题分析与整理(二)
  15. 数据结构课设----运动会分数统计系统
  16. python太极代码_Python turtle绘制阴阳太极图代码解析
  17. ErrMsg:server is DOWN now, please try again later!
  18. Java学习_Day 10(学习内容:尚硅谷集合JAVA零基础P523-P533)
  19. 编码器-解码器(seq2seq)
  20. coreseek-4.1-win32版本下windows安装记录

热门文章

  1. python_MODIS HDF数据转为tif并拼接图像
  2. 天天用注解,你知道注解到底是怎样实现的吗?
  3. origin绘制投影能带-颜色渐变图(color Mapped)
  4. django搭建 - windos 服务器配置与设置
  5. GitHub标星65k,阿里面试核心技术手册,我不允许还有人没看过!
  6. Apache配置虚拟主机无效
  7. Vue+springboot居民户籍居住证管理系统
  8. 8月6号首考雅思回忆
  9. 曝阿里达摩院大模型 M6 带头人杨红霞已离职:个人选择,非行业原因
  10. 自适应的永磁同步电MRAS无位置传感器控制 sinulink仿真 MRAS无传感器控制 交流异步电机