php+grpc+protobuf整合(php客户端+go服务端)

PHP客户端环境

本人使用为debian系统下的docker容器安装的php-fpm镜像,php-fpm7.1.13镜像承载系统为alpine;

需要安装工具

protoc: 将proto文件生成为php文件的编译器

grpc_php_plugin: protoc生成关于grpc的php文件的插件

grpc.so: php的grpc扩展

protobuf.so: php的protobuf扩展

debian系统安装protoc

下载地址:https://github.com/protocolbuffers/protobuf/releases 选择对应安装版本下载之后解压;

将解压的后的 bin/protoc 文件添加到环境变量目录里;

通过命令:

root@iZ2zebyhcs68uwq5kc8ioxZ:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin

可以看到所有的环境变量目录;

运行代码:

[root@VM_179_192_centos ~]# protoc --version
libprotoc 3.6.1

表示成功;

debian系统安装grpc_php_plugin插件

先创建个目录存放将要git下来的grpc文件 例如:/app/grpcDemo

$ cd /app/
$ git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc   grpcDemo
$ cd grpcDemo
$ git submodule update --init
$ make grpc_php_plugin

执行成功后会在grpc的bins/opt 目录中看到grpc_php_plugin插件,在后面protoc生成grpc的php文件时会用到;

alpine系统内grpc.so安装

使用pecl安装即可,当然如果想要自己编译,也可以

$ pecl install grpc

一般会缺少一些编译工具,所以最好先安装对应编译工具

$ apk add --no-cache libstdc++
$ apk add --no-cache --update git make g++ unzip autoconf automake libtool file openssl curl

参考:https://github.com/c9s/alpine-grpc-dev/blob/master/edge/Dockerfile

安装 grpc成功后,默认的grpc.so文件已放在对应目录内,此时需要在php.ini内引入grpc.so扩展文件

$ vi /usr/local/etc/php/conf.d/docker-php-ext-grpc.ini

extension=grpc.so

alpine系统内protobuf.so安装

同上和grpc.so类似安装

$ pecl install protobuf

安装 protobuf成功后,默认的protobuf.so文件已放在对应目录内,此时需要在php.ini内引入protobuf.so扩展文件

$ vi /usr/local/etc/php/conf.d/docker-php-ext-protobuf.ini

extension=protobuf.so

注意:为了能够使用grpc扩展,还需要在项目里composer安装grpc文件才行,运行php项目需要使用此vendor

composer require grpc/grpc

PHP客户端程序部署

protoc生成php文件

作为demo的proto文件helloworld.proto

syntax = "proto3";

package helloworld;

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

只生成proto文件的话,不需要grpc_php_plugin插件,使用命令:

protoc --php_out=./ helloworld.proto

上面的方法只生成所有的proto对应的类,不生成实现grpc接口的stub client类。 使用下面的方法能同时生成stup client类

protoc --php_out=./ --grpc_out=./   --plugin=protoc-gen-grpc=/app/grpcDemo/bins/opt/grpc_php_plugin   helloworld.proto

php程序实现:thinkphp5.1.16语法

namespace app\proto\controller;
/**
 * Description of Demo
 * Date 2018年11月11日 13:22:05
 * @author Carter
*/
use Helloworld\GreeterClient;
use GPBMetadata\Helloworld;
use Helloworld\HelloRequest;
use Helloworld\HelloReply;
class Demo{
    //grpc客户端实现
      public function greet()
      {
          debug('begin');
          $client = new GreeterClient('***.**.**.**:50051', ['credentials' => \Grpc\ChannelCredentials::createInsecure(),]);
          $request = new HelloRequest();
          $name = "world";
          $request->setName($name);
          list($reply, $status) = $client->SayHello($request)->wait();
          $message = $reply->getMessage();
          debug('end');
          echo "消耗时间:".debug('begin','end').'s'."\n";
          echo "消耗内存:".debug('begin','end','m')."\n";
          echo $message."\n";
      }
}

go服务端环境

本人使用服务器为centos7.2,配合go1.9.2环境

需要安装的工具

go环境安装:1.9.2版本

grpc和protobuf资源包:相当于扩展

protoc: 将proto文件生成为go文件的编译器

go环境安装

$ wget https://www.golangtc.com/static/go/1.9.2/go1.9.2.linux-amd64.tar.gz

解压到某目录,我这里解压到/usr/local/go目录;

然后将此目录添加为环境变量目录

设置环境变量
$ vim /etc/profile
添加
export GOROOT=/usr/local/go   //安装目录
export GOPATH=/app/goDemo    //项目目录
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin   //项目执行文件目录

保存
esc
:wq

创建项目目录 /app/goDemo,以及附属的子目录 src,bin,pkg;

执行命令:

[root@VM_179_192_centos go]# go version
go version go1.9.2 linux/amd64

grpc和protobuf资源包

go get https://github.com/golang/protobuf
go get https://github.com/grpc/grpc-go

protoc安装

go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go

编译helloworld.proto文件生成对应go文件

protoc --go_out=plugins=grpc:. helloworld.proto

go服务端程序部署

在 /app/goDemo/src下新建greeter_server/main.go文件 代码:

package main

import (
        "context"
        "log"
        "net"

        "google.golang.org/grpc"
        pb "helloworld"
        "google.golang.org/grpc/reflection"
)

const (
        port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
        return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
        lis, err := net.Listen("tcp", port)
        if err != nil {
                log.Fatalf("failed to listen: %v", err)
        }
        s := grpc.NewServer()
        pb.RegisterGreeterServer(s, &server{})
        // Register reflection service on gRPC server.
        reflection.Register(s)
        if err := s.Serve(lis); err != nil {
                log.Fatalf("failed to serve: %v", err)
        }
}

注意:因为翻墙原因,程序引入的一些包不会成功,所以需要自己从github查找到对应的资源,放在这些资源包里;

例如:

go get https://github.com/grpc/grpc-go google.golang.org/grpc

然后就可以运行服务端程序了

go run main.go

对应的php客户端开始访问即可:

http://***.**.**.**/proto/demo/greet

返回结果:

消耗时间:0.051832s 消耗内存:12.79 KB Hello world

go客户端环境测试

go客户端代码:使用http包测go客户端也可以,使用程序测也可以,这里使用启动go客户端启动http服务后,测http请求

go客户端代码

新建 greeter_cient/main.go 文件

package main

import (
	"context"
	"log"
	"os"
	"time"
	"net/http"
	"google.golang.org/grpc"
	pb "helloworld"
)

const (
	address     = "localhost:50051"
	defaultName = "world"
)

func sayhelloName(w http.ResponseWriter,r *http.Request) {
	// Set up a connection to the server.
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	// Contact the server and print out its response.
	name := defaultName
	if len(os.Args) > 1 {
		name = os.Args[1]
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("GreetingGreeting: %s", r.Message)
}

func main(){
	http.HandleFunc("/",sayhelloName)  //设置访问的路由
	err := http.ListenAndServe(":9090",nil)   //设置监听的端口
	if err != nil{
		log.Fatal("ListenAndServe:",err)
	}
}

启动go客户端http服务

$ go run main.go

HTTP请求go客户端

http://**.**.**.**:9090/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值