跳至正文

PHP + GO +GRPC详细使用方法

一、生成proto文件和grpc代码
创建文件:hello.proto,内容如下:

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;
}

生成go语言文件:

#在hello.proto文件目录下执行
protoc -I. --go_out=plugins=grpc:./ ./*.proto

执行成功后会生成一个hello.pb.go文件

hello.pb.go的包名为proto,后续写服务端和客户端代码需要引入此文件

编写go服务端代码,server.go:

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()
}

编写go客户端代码,client.go:

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()
}

生成php语言文件:

#在hello.proto文件目录下执行
protoc --proto_path=./ --php_out=./ --grpc_out=./ --plugin=protoc-gen-grpc=(这里改成你实际生成grpc_php_plugin的路径) ./*.proto

执行成功后会生成以下几个文件:

编写php客户端代码,client.php:

<?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());

如果你是第一次使用,还需要配置composer:

#安装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    

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注