云海的博客
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)

云海

服务端研发
首页
  • 接口
  • 数组
  • slice
  • map
  • 指针
  • 反射
  • Context
  • sync.map
  • 锁
  • 类型和类型指针分析
  • recover
  • 从零实现RPC框架
  • make和new区别
  • channel
  • sync.Once
  • sync.Pool
  • protobuf
  • MongoDB pkg源码-findone
  • MyBatis
  • Maven
  • 解析Laravel框架—路由处理
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
  • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
  • Docker使用笔记-常用命令
  • Docker使用笔记-容器间通讯
  • Docker使用笔记-搭建Redis集群
  • Docker使用笔记-镜像多阶段构建
  • Kubernetes部署golang服务
  • Linux常用命令
  • Docker安装Prometheus与Grafana
  • Protobuf
  • TCP抓包
  • 概述-《TCP/IP详解》读书笔记
  • 索引
  • 事务隔离级别
  • 常识
  • 每日一题(1)
  • 每日一题(2)
  • 每日一题(3)
  • 每日一题(4)
关于
GitHub (opens new window)
  • 基础
  • gRPC拦截器
  • PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信
    • JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信
    • gRPC系列
    云海
    2021-03-29
    目录

    PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信

    # 概述

    从零开始讲解,PHP(客户端)与 Golang(服务端)使用grpc+protobuf 通信。因为我本地环境都是配置好的,避免我落下步骤操作,所以我在docker环境下开发,拉取一个基于Alpine的镜像。Alpine操作系统是一个面向安全的轻型 Linux 发行版。

    # 正文

    搭建环境

    1.项目中,我会用到composer以及PHP相关的扩展,于是我拉取一个基于PHP7.2的docker镜像。命令中的参数,可以看我另一篇文章,Docker 使用笔记-常用基础命令。

    docker container run -it --name grpc-ubuntu -v /Users/wuerzhilv-lq/examples:/home/examples lorisleiva/laravel-docker:7.2 /bin/bash
    
    1

    2.安装相关的包

    apk add autoconf automake libtool linux-headers  
    
    1

    3.这个docker没有golang语言环境,我们这里安装下。这里采用编译安装的方式,为什么不用apk包管理器安装,因为Go工具链是用Go编写的,要构建它,需要安装Go编译器;由于我们没有GO编译器,同时1.4以后的GO语言版本没有直接支持GCC,支持GO编译器和GCCGO,因此我们需要先现在1. 4版本的GO,利用GCC编译好GO编译器后,再利用1.4版本的GO编译器编译最新版本的GO(比如以下的1.14)。

    ①下载go1.4版本,源码从官方下载
    wget https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz
    tar -zxf go1.4-bootstrap-20171003.tar.gz
    mv go /usr/local/go1.4
    
    1
    2
    3
    4
    ②下载go1.14版本
    wget  https://dl.google.com/go/go1.14.2.src.tar.gz
    tar -zxf go1.14.2.src.tar.gz
    mv go /usr/local/go
    
    1
    2
    3
    4
    ③环境变量设置(GOROOT_BOOTSTRAP是编译器环境设定需要)
    echo 'export GOROOT_BOOTSTRAP=/usr/local/go1.4' >> ~/.bash_profile
    echo 'export GOROOT=/usr/local/go' >> ~/.bash_profile
    echo 'export PATH=${GOROOT}/bin:${PATH}' >> ~/.bash_profile
    //重载环境配置变量(主要是重载GOROOT_BOOTSTRAP)
    source ~/.bash_profile
    
    1
    2
    3
    4
    5
    6
    ④ 编译go1.4的版本 
    cd /usr/local/go1.4/src && ./make.bash
    
    1
    2
    ⑤利用go1.4的go编译器,编译go1.14
    cd /usr/local/go/src && ./make.bash
    
    1
    2
    ⑥查看golang版本
    go version
    
    1
    2

    4.新下载的php本来就没有现成的php.ini文件。只是给了php.ini-development (开发环境用)与 php.ini-production(生产环境用)两个建议。这里我们基于生产环境,复制出一个php.ini文件。

    cp /usr/local/etc/php/php.ini-production  /usr/local/etc/php/php.ini
    
    1

    5.系统层面的,我们环境就安装好了。Grpc 是使用protobuf来传输数据,protobuf是一个文件,那怎么让php和golang语言识别它,这里就需要一个编译工具了。

    apk add protobuf
    
    1
    1. PHP安装Grpc,Protobuf扩展。
    pecl install grpc-1.25.0
    pecl install protobuf-3.11.4
    
    1
    2

    打开我们新建的php.ini文件,将扩展加进去。可以使用php -m 查看配置是否生效。

    extension=grpc.so    
    extension=protobuf.so
    
    1
    2

    7.安装PHP Protoc Plugin

    第一种方法:

    $ git clone -b v1.28.1 https://github.com/grpc/grpc
    $ cd grpc
    $ git submodule update --init
    $ make grpc_php_plugin
    
    1
    2
    3
    4

    make编译后,输出目录为bins/opt,输出文件grpc_php_plugin,将文件复制到/home/examples

    cp bins/opt/grpc_php_plugin  /home/examples/
    
    1

    第二种方法:

    bazel build src/compiler:grpc_php_plugin
    
    1

    8.安装Golang Protoc Plugin

    go get -u github.com/golang/protobuf/protoc-gen-go
    export PATH=$PATH:$GOPATH/bin
    
    1
    2

    9.安装grpc

    go get -u google.golang.org/grpc
    
    1

    10.环境都配好了,我们来写项目代码,我在创建docker容器的时候,就把容器目录挂载到了本地,可以使用ide工具开发。

    我这里配置的本地目录是,/Users/wuerzhilv-lq/examples。examples就相当于项目目录了,在这个项目中新建protos目录,用于存放protobuf文件;新建php目录用于存放客户端代码;新建go目录,用于存放服务端代码。

    我们新建一个protobuf文件(helloworld.proto),来定义服务方法,请求参数,请求返回值。 内容如下

    // 定义语法,一共是有两种proto2,proto3。我这里使用proto3。
    syntax = "proto3";
    
    // 定义服务(我感觉像类)
    service Greeter {
      // 定义服务方法为SayHello,可以有多个方法
      rpc SayHello (HelloRequest) returns (HelloReply) {}
    }
    
    //定义请求参数
    message HelloRequest {
      string name = 1;
    }
    
    //定义返回参数
    message HelloReply {
       string message = 1;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    1. 服务端代码,进入容器中的项目目录,根据protobuf文件,使用proto工具生成服务端(golang)代码到go目录。执行命令之后,会在go文件夹中出现一个proto文件夹,里面包含一个helloworld.pb.go文件。
    protoc protos/helloworld.proto --go_out=plugins=grpc:go
    
    1

    在examples/go 文件夹中,新建一个main.go文件,注册helloworld服务。

    package main
    
    import (
        "context"
        "log"
        "net"
    
        "google.golang.org/grpc"
        pb "./protos"
    )
    
    const (
        port = ":50051"
    )
    
    // server is used to implement helloworld.GreeterServer.
    type server struct {
        pb.UnimplementedGreeterServer
    }
    
    // SayHello implements helloworld.GreeterServer
    func (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() {
        lis, err := net.Listen("tcp", port)
        if err != nil {
            log.Fatalf("failed to listen: %v", err)
        }
        s := grpc.NewServer()
        pb.RegisterGreeterServer(s, &server{})
        log.Printf("服务启动"+port)
        if err := s.Serve(lis); err != nil {
            log.Fatalf("failed to serve: %v", err)
        }
    }
    
    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
    36
    37
    38

    运行go run main.go启动服务,看看服务是否能启动。

    12.客户端代码,进入容器中的项目目录,根据protobuf文件,使用proto工具生成客户端(PHP)代码到php目录。执行命令之后,会在php文件夹中出现一些文件。

    protoc --proto_path=protos   --php_out=php   --grpc_out=php   --plugin=protoc-gen-grpc=/home/examples/grpc_php_plugin protos/helloworld.proto
    
    1

    更换composer源

    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
    
    1

    通过composer工具,我们初始化一个composer.json文件。

    composer.json内容如下:

    {
      "name": "grpc/grpc-demo",
      "description": "gRPC example for PHP",
      "require": {
        "grpc/grpc": "^1.27",
        "google/protobuf": "^3.11"
      },
      "authors": [
        {
          "name": "Li",
          "email": "calmliqi@gmail.com"
        }
      ]
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    composer install 安装扩展包。

    在php目录下,新建客户端文件,greeter_client.php

    <?php
    
    require dirname(__FILE__).'/vendor/autoload.php';
    
    @include_once dirname(__FILE__).'/Helloworld/GreeterClient.php';
    @include_once dirname(__FILE__).'/Helloworld/HelloReply.php';
    @include_once dirname(__FILE__).'/Helloworld/HelloRequest.php';
    @include_once dirname(__FILE__).'/GPBMetadata/Helloworld.php';
    
    function greet($name)
    {
        $client = new Helloworld\GreeterClient('localhost:50051', [
            'credentials' => Grpc\ChannelCredentials::createInsecure(),
        ]);
        $request = new Helloworld\HelloRequest();
        $request->setName($name);
        list($reply, $status) = $client->SayHello($request)->wait();
        $message = $reply->getMessage();
    
        return $message;
    }
    
    $name = !empty($argv[1]) ? $argv[1] : 'world';
    echo greet($name)."\n";
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    13.进入examples项目目录,

    启动服务端

    go run go/main.go
    
    1

    执行客户端

    php php/greeter_client.php
    
    1

    如果输出helloworld,那就是成功了。

    # 总结:

    这篇文章,只是简单粗略说了下,Grpc+protobuf的使用,比如针对protobuf文件,具体的内容没有说。以后,我会在写一篇针对protobuf文件详细讲解的文章。我懂得也不是太多,就是当自己做了一次总结。如有不对的地方,大家多提意见。我本机挂了代理,所以没有遇到墙的问题,如果被墙了,自行百度吧。 参考了如下资料:

    https://developers.google.com/protocol-buffers

    https://grpc.io/docs/quickstart

    https://golang.org/doc/install/source

    https://tkstorm.com/posts-list/programming/go/build-golang-from-source-on-alpine/

    上次更新: 2023/06/05
    gRPC拦截器
    JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信

    ← gRPC拦截器 JAVA(客户端)与 Golang(服务端) 使用grpc+protobuf通信→

    最近更新
    01
    函数
    04-11
    02
    面试题
    04-11
    03
    EFK日志收集系统单机版
    08-18
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式