Please enable Javascript to view the contents

Grpc通信之php客户端与golang服务端

 ·  ☕ 3 分钟 · 👀... 阅读

Grpc通信之php客户端与golang服务端

  • grpc
  • 服务端 golang iris
  • 客户端 php laravel

golang 服务端

  • 创建项目
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

mkdir iris-example

cd iris-example

go mod init iris-example

go mod tidy

 

安装gRPC和Protobuf

https://grpc.io/docs/languages/go/quickstart/

1
2
3
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

定义proto 文件

api/protos/test/test.proto

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

// 指定proto版本
syntax = "proto3";  

// 指定默认包名
package test;  

// 指定golang包名
option go_package = ".;test";  
  
  
// The greeting service definition.  
service Greeter {  
  // Sends a greeting  
  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;  
}

生成go的grpc代码

  • –go_out=. 表示输出的文件夹,需要我们自己创建 .当前文件夹

  • go_opt=paths=source_relative 表示按源文件的目录组织输出,也就是" the same relative directory “,
    这意味着,会将proto文件相对proto_path指定的基目录,按同样的目录组织,在$go_out上重放一遍

一般都会使用source_relative,否则,就会按照option go_package里面的那个路径生成

iris-example 根目录执行

1
protoc --go_out=. --go_opt=paths=source_relative  --go-grpc_out=. --go-grpc_opt=paths=source_relative api/protos/test/test.proto

创建protos目录,在此目录下创建proto 文件 目录结构如下

1
2
3
4
5
6
7
8
9
#iris-example
#├──api
#├──└── protos
#│    └── test
#│        ├── test.pb.go
#│        ├── test.proto
#│        └── test_grpc.pb.go
#├──server
#├──└── grpc_server.go

实现服务端接口 server/grpc_server.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Package main implements a server for Greeter service.  
package main  
  
import (  
   "context"  
   "flag"   "fmt"   pb "iris-example/api/protos/test"  
   "log"   "net"  
   "google.golang.org/grpc")  
  
var (  
   port = flag.Int("port", 50051, "The server port")  
)  
  
// server is used to implement helloworld.GreeterServer.type server struct {  
   pb.UnimplementedGreeterServer  
}  
  
// SayHello implements helloworld.GreeterServerfunc (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {  
   log.Printf("Received: %v", in.GetName())  
   return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil  
}  
  
func main() {  
   flag.Parse()  
   lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))  
   if err != nil {  
      log.Fatalf("failed to listen: %v", err)  
   }  
   s := grpc.NewServer()  
   pb.RegisterGreeterServer(s, &server{})  
   log.Printf("server listening at %v", lis.Addr())  
   if err := s.Serve(lis); err != nil {  
      log.Fatalf("failed to serve: %v", err)  
   }  
}

启动服务

1
go run server/grpc_server.go

创建PHP客户端

laravel 项目

安装php扩展

1
2
pecl install protobuf
pecl install grpc

编译安装protoc的grpc_php_plugin插件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 下载对应分支(对应版本的)grpc
git clone -b RELEASE_TAG_HERE https://gitee.com/github-fast-sync/grpc

cd grpc

# 下载子模块
git submodule update --init

mkdir -p cmake/build
cd cmake/build
# 编译 protoc 与 grpc_php_olugin makefile 文件
cmake ../..

# 编译 makefile文件 生成可执行文件
make protoc grpc_php_plugin

# 编译完成后将grpc_php_plugin 移动到 /usr/local/bin 目录下
 mv grpc_php_plugin /usr/local/bin

生成PHP的gRPC客户端代码

在laravel根目录执行

1
protoc -I=../iris-example/api/protos/ --php_out=./grpc --grpc_out=./grpc --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin  ../iris-example/api/protos/test/test.proto
  • -I(等同–proto_path) 用于表示要编译的proto文件所依赖的其他proto文件的查找位置,可以使用-I来替代。如果没有指定则从当前目录中查找

  • –php_out php代码输出路径,里面包含request,response,client代码。

  • –grpc_out GPBMetadata输出路径,用于保存.proto的二进制元数据

  • –plugin 生成代码插件的类型与插件的绝对路径路径

  • 最后 定义好的proto文件路径

生成目录

# laravel-example-app
grpc
├── GPBMetadata  # 二进制元数据
│   └── Test
│       └── Test.php
└── Test  # 客户端代码
    ├── GreeterClient.php
    ├── HelloReply.php
    └── HelloRequest.php

grpc 放在 composer.jsonautoload/psr-4

1
2
3
4
5
6
7
8
9
"autoload": {  
    "psr-4": {  
        "App\\": "app/",  
        "Database\\Factories\\": "database/factories/",  
        "Database\\Seeders\\": "database/seeders/",  
        "GPBMetadata\\":"grpc/GPBMetadata/",  
        "Test\\":"grpc/Test/"  
    } 
},

添加composer相关依赖

1
2
composer require google/protobuf
composer require grpc/grpc

客户端调佣服务端

创建app/Http/Controllers/TestController 控制器,新建grpc方法,代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php  
declare(strict_types=1);  
  
namespace App\Http\Controllers;  
    
use Grpc\ChannelCredentials;    
use Test\GreeterClient;  
use Test\HelloReply;
use Test\HelloRequest;  
  
class TestController extends Controller  
{  

    public function grpc(): JsonResponse
    {
        $host    = 'localhost:50051';
        $client  = new GreeterClient($host, [
            'credentials' => ChannelCredentials::createInsecure(),
        ]);
        $name    = 'world';
        $request = new HelloRequest();
        $request->setName($name);
        $call = $client->SayHello($request);
        /**
         * @var HelloReply $response
         */
        list($response, $status) = $call->wait();
        $data = [
            'status' => $status,
            'message' => $response->getMessage()
        ];
        return response()->json($data,200, [], JSON_UNESCAPED_UNICODE);
    }
}

routes/api.php文件增加路由

1
Route::get("grpc",[TestController::class, 'grpc']);

启动laravel

1
php artisan serve

请求服务器

浏览器访问 http://127.0.0.1:8000/api/grpc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "status": {
    "metadata": [
      
    ],
    "code": 0,
    "details": ""
  },
  "message": "Hello world"
}

输出以上内容就成功了。

分享

Jade
作者
Jade
📚Learner🌐Web Developer


目录