php(客户端)/golang(客户端) 使用grpc,protobuf调用 golang(服务端)

php客户端/golang客户端使用grpc,protobuf调用 golang服务端

    • golang服务端
    • golang客户端
    • php客户端

在使用之前,必须要安装好相应的grpc与protobuf, 可参考GO与PHP有关grpc,protobuf安装方法

golang服务端

1.使用go mod 创建文件go_grpc_service
https://goproxy.cn : 七牛云赞助支持的开源代理
https://mirrors.aliyun.com/goproxy/ : 阿里云官方维护的go代理
https://goproxy.io/ : 也是一个开源的go代理

go mod init go_grpc_service
set GOPROXY=https://goproxy.io
go mod tidy
go mod download
go mod vendor

2.创建Protobuf文件
在项目里面创建pdfiles目录,在此目录下创建Prod.proto文件,写入下面代码

syntax="proto3"; // 指定proto版本
package services;  // 指定默认包名
// 指定golang包名
option go_package = "./;services";

message ProdRequest{
     
  int32 prod_id=1; //传入的商品id
}
message ProdResponse{
     
  int32 prod_stock=1; //商品库存
}
// 定义服务
service ProdService {
     
    rpc SayHello (ProdRequest) returns (ProdResponse) {
     }
}

创建services目录(用于生产go文件) 与pdfiles目录同级
在pdfiles目录下执行下面命令(–go_out 输出go格式文件,services:生成的go文件所放在的目录名):

protoc --go_out=plugins=grpc:../services  Prod.proto

生成以下文件

go_grpc_service
├── pdfiles
│   └── Prod.proto
├── services
│   ├── Prod.pb.go

在services目录下创建service.go

package services
import "context"
type  ProdService struct {
     
}
func (this ProdService) SayHello(ctx context.Context, req *ProdRequest) (*ProdResponse, error)  {
     
    resp := new(ProdResponse)
	resp.ProdStock = req.ProdId
	return resp, nil
}

go_grpc_service目录下创建main.go

package main

import (
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"
	"go_grpc_service/services"
	"net"
)
func main()  {
     
	listen, err := net.Listen("tcp", ":8002")
	if err != nil {
     
		grpclog.Fatalf("Failed to listen: %v", err)
	}
    // 实例化grpc Server
	s := grpc.NewServer()
   // 注册ProdService
	services.RegisterProdServiceServer(s, services.ProdService{
     })
    fmt.Println("Listen on 8002" )
	s.Serve(listen)
}

golang客户端

1.使用go mod 创建文件go_grpc_client

go mod init go_grpc_client

go mod tidy
go mod download
go mod vendor

2.把Prod.pb.go文件拷贝到services目录下
3.go_grpc_client目录下创建main.go

 package main

import (
	"context"
	"fmt"
	"go_grpc_client/services"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"
)
func main()  {
     
	// 连接
	conn, err := grpc.Dial("127.0.0.1:8002", grpc.WithInsecure())
	if err != nil {
     
		grpclog.Fatalln(err)
	}
	defer conn.Close()

	// 初始化客户端
	c := services.NewProdServiceClient(conn)
	// 调用方法
	//客户端初始化连接后直接调用Prod.pb.go中实现的SayHello方法,即可向服务端发起请求,就像调用本地方法一样。
	req := &services.ProdRequest{
     ProdId:58}
	res, err := c.SayHello(context.Background(), req)
	if err != nil {
     
		grpclog.Fatalln(err)
	}
	fmt.Println(res)
}

php客户端

创建目录php_grpc_client,把Prod.proto放在该目录中
Prod.proto代码

syntax="proto3"; // 指定proto版本
package services;  // 指定默认包名

message ProdRequest{
     
  int32 prod_id=1; //传入的商品id
}
message ProdResponse{
     
  int32 prod_stock=1; //商品库存
}
// 定义服务
service ProdService {
     
    rpc SayHello (ProdRequest) returns (ProdResponse) {
     }
}

不带客户端

protoc --proto_path=./ --php_out=./  Prod.proto 

生成带客户端的 (grpc_php_plugin 生成带客户端,grpc_php_plugin路径代表安装路径,以通过find / -name grpc_php_plugin 查看)

protoc --proto_path=./ --plugin=protoc-gen-grpc=/usr/local/src/grpc/cmake/build/grpc_php_plugin --php_out=./ --grpc_out=./ Prod.proto 

生成以下文件

├── GPBMetadata
│   └── Prod.php
├── Services
│   ├── ProdRequest.php
│   ├── ProdResponse.php
│   ├── ProdServiceClient.php
└── Prod.proto

创建index.php


require_once __DIR__ . '/vendor/autoload.php';

use \Grpc\ChannelCredentials;
use \Services\ProdServiceClient;
use \Services\ProdRequest;
use \Services\ProdResponse;
//127.0.0.1:8002 服务端的端口
$helloClient = new ProdServiceClient('127.0.0.1:8002', [
    'credentials' => ChannelCredentials::createInsecure()
]);

$helloRequest = new ProdRequest();
$helloRequest->setProdId(519);
$request = $helloClient->SayHello($helloRequest)->wait();

/** @var HelloReply $response */
list($response, $status) = $request;
var_dump($request);
echo PHP_EOL;
$message = $response->getProdStock();
var_dump($message);
?>

composer.json文件添加以下

"autoload":{
        "psr-4":{
            "GPBMetadata\\":"GPBMetadata/",
            "Services\\":"Services/",
            "Grpc\\":"Grpc/"
        }
    }

修改完 composer.json 的 autoload 字段后需要更新一下 Composer 的自动加载类:

composer dumpautoload -o

执行 php index.php (前提先开启golang的服务)

你可能感兴趣的:(golang,go,protobuf)