测试环境:win10、centos7.9、php7.4、golang1.17
1、protoc的源码和各个系统的预编译包 - https://github.com/protocolbuffers/protobuf/releases
2、选择对应的安装文件下载,解压(tips:文件解压的路径最好是英文,无任何特殊字符,包括空格;之前安装es插件时就因为Program
Files中有个空格,导致安装失败)
protoc --version #查看protoc的版本
版本信息打印如下:
libprotoc 3.13.0
#安装PECL
wget http://pear.php.net/go-pear.phar
php go-pear.phar
#php版本 < 7
yum install php-pear
#安装grpc、protobuf扩展
pecl install protobuf
pecl install grpc
方法1,升级camke版本
参考:https://blog.csdn.net/CrystalShaw/article/details/120043042
方法2,降低grpc版本
#可以到pecl选一个版本,http://pecl.php.net/package/gRPC
#如:
pecl install grpc-1.31.1
安装成功后,需要将生成的grpc.so和protobuf.so文件移动到php扩展目录下,并加载到php.ini中,如:
#扩展路径请改为你实际的路径
extension = /www/server/php/74/lib/php/extensions/no-debug-non-zts-20190902/protobuf.so
extension = /www/server/php/74/lib/php/extensions/no-debug-non-zts-20190902/grpc.so
git clone https://github.com/grpc/grpc
cd grpc
git submodule update --init
mkdir -p cmake/build
cd cmake/build
cmake ../..
make protoc grpc_php_plugin
mv ./grpc_php_plugin /opt/homebrew/bin/
如果是国内服务器,一直安装不成功,其原因众所周知无非就是有些东西需要科学上网
找到项目的.gitmodules文件,这个文件就是子工程的clone path 以及clone的位置:
我们只需要找到url对应的可访问地址,这里给出两个结局的方案,也是我常用的方案:
1、使用github镜像地址:http://git.what996.com
2、在gitee上找别人fork好的对应项目的地址
这里我们使用第一种,将url的https://github.com换成http://git.what996.com
然后在执行git submodule update --init就ok了
syntax = "proto3";
package services;
option go_package = "./;proto";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
int64 len = 2;
}
#在hello.proto文件目录下执行
protoc -I. --go_out=plugins=grpc:./ ./*.proto
hello.pb.go的包名为proto,后续写服务端和客户端代码需要引入此文件
package main
import (
"context"
"fmt"
"proto" #引入生成的go文件,路径改成你实际的引入路径
"google.golang.org/grpc"
"net"
)
// 服务端
var Server = new(server)
type server struct{}
// 业务逻辑
func (s *server) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply, error) {
res := &proto.HelloReply{
Message: "hello " + request.Name,
Len: 101,
}
fmt.Print("SayHello成功调用..\r\n")
return res, nil
}
// 启动rpc的server服务
func (s *server) Start() {
// 1.实例化server
g := grpc.NewServer()
// 2.注册逻辑到server中
proto.RegisterGreeterServer(g, &server{})
// 3.启动server
lis, err := net.Listen("tcp", ":8399")
if err != nil {
panic("监听错误:" + err.Error())
}
fmt.Print("grpc启动服务成功..\r\n")
err = g.Serve(lis)
fmt.Print("err:", err)
if err != nil {
panic("grpc服务端运行错误:" + err.Error())
}
}
func main() {
Server.Start()
}
package main
import (
"context"
"fmt"
"proto" #引入生成的go文件,路径改成你实际的引入路径
"google.golang.org/grpc"
)
// rpc调用
func clientRpc(body map[string]string) (res *proto.HelloReply, err error) {
name := body["name"]
conn, err := grpc.Dial("localhost:8399", grpc.WithInsecure())
if err != nil {
return nil, err
}
defer conn.Close()
rpc := proto.NewGreeterClient(conn)
response, err := rpc.SayHello(context.Background(), &proto.HelloRequest{Name: name})
if err != nil {
return nil, err
}
return response, nil
}
// 业务代码
func start() {
body := make(map[string]string)
body["name"] = "niubi!"
response, err := clientRpc(body)
if err != nil {
fmt.Println("rpc调用失败:", err)
return
}
fmt.Println(response.Message)
}
func main() {
start()
}
#在hello.proto文件目录下执行
protoc --proto_path=./ --php_out=.. --grpc_out=.. --plugin=protoc-gen-grpc=(这里改成你实际生成grpc_php_plugin的路径) ./*.proto
<?php
require dirname(__FILE__) . '/vendor/autoload.php';
$hostname = 'localhost:8399';
$client = new \Services\GreeterClient(
$hostname, [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]
);
$indexRequest = new \Services\HelloRequest();
$indexRequest->setName($name = '测试');
/**
* @var \Services\HelloReply $response
*/
[$response, $status] = $client->SayHello($indexRequest)->wait();
if ($status->code !== Grpc\STATUS_OK) {
echo "ERROR: " . $status->code . ", " . $status->details . PHP_EOL;
}
var_export($response->serializeToJsonString());
#安装grpc扩展包
composer require google/protobuf
composer require grpc/grpc
#将生成的php类文件加载到composer ,注意路径改成你实际的路径
"autoload":{
"psr-4":{
"GPBMetadata\\":"common/grpc/GPBMetadata/",
"Services\\":"common/grpc/Services/"
}
}
# 更新composer配置
composer update
#go服务端:
go run server.go
#go客户端:
go run client.go
#php客户端:
php client.php