APP下载

gRPC入坑记

消息来源:baojiabao.com 作者: 发布时间:2024-11-29

报价宝综合消息gRPC入坑记

概要

由于gRPC主要是Google开发的,由于一些已知的原因,gRPC跑demo还是不那么顺利的。单独写这一篇,主要是gRPC安装过程中的坑太多了,记录下来让大家少走弯路。

主要的坑:

如果使用PHP、Python开发gRPC的客户端,需要编译gRPC命令列工具,生成proto的程式码生成外挂,否则proto里定义的service无法编译出来。编译需要使用GCC4.8级以上版本,否则报不支援C++11。然后需要龟速下周grpc源代码,并下载一大堆第三方依赖。这个过程非常痛苦。使用golang、java的可以忽略。PHP还需要按照grpc的c扩充套件。编译需要使用GCC4.8级以上版本。如果使用golang开发服务,依赖的第三方服务基本是下载不下来的,需要使用go mod增加对映规则到github仓库,github下载也是龟速。本文讲解gRPC demo的同时,会介绍如何解决这些坑。本文对应的Github地址:https://github.com/52fhy/grpc-sample 。该仓库储存了demo示例,以及部分系统编译好的二进位制包,大家觉得有些步骤里耗时实在太长了,可以直接clone该仓库,复制二进位制包到对应目录(仅限测试开发,生产环境还是老老实实自己编译吧)。

升级GCC

gRPC命令列工具编译需要使用 GCC4.8及以上版本。CentOS6系列的内建版本是GCC4.7。

使用gcc --version可以检视版本。

如果你的系统GCC版本>=4.8,可以忽略本节。如果仅使用golang、java,请忽略本节。

注:不建议大家下载GCC源代码包或者使用yum下载GCC4.8及以上版本,原因:

1) 源代码包安装真的是非常非常的慢 2) yum 源下载速度慢的像蜗牛。下面的SCL安装方法是推荐大家用的,安装好后原来的版本还能用。

如果需要升级gcc至4.8或更高版本,建议直接采用安装SCL源之后安装devtoolset-6(devtoolset-6目前gcc版本为6.3),因为devtoolset-4及之前的版本都已经结束支援,只能通过其他方法安装。

升级到gcc 6.3:

Copy

yum -y install centos-release-scl

yum -y install devtoolset-6-gcc devtoolset-6-gcc-c++ devtoolset-6-binutils

scl enable devtoolset-6 bash

需要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。如果要长期使用gcc 6.3的话:

Copy

echo "source /opt/rh/devtoolset-6/enable" >>/etc/profile

这样退出shell重新开启就是新版的gcc了。其它版本同理。

升级到gcc 7.3:

Copy

yum -y install centos-release-scl

yum -y install devtoolset-7-gcc devtoolset-7-gcc-c++ devtoolset-7-binutils

scl enable devtoolset-7 bash

已经停止支援的devtoolset4(gcc 5.2)及之前版本的安装方法,可能比较慢,大家感兴趣的话可以尝试。

升级到gcc 4.8:

Copy

wget http://people.centos.org/tru/devtools-2/devtools-2.repo -O /etc/yum.repos.d/devtoolset-2.repo

yum -y install devtoolset-2-gcc devtoolset-2-gcc-c++ devtoolset-2-binutils

scl enable devtoolset-2 bash

升级到gcc4.9:

Copy

wget https://copr.fedoraproject.org/coprs/rhscl/devtoolset-3/repo/epel-6/rhscl-devtoolset-3-epel-6.repo -O /etc/yum.repos.d/devtoolset-3.repo

yum -y install devtoolset-3-gcc devtoolset-3-gcc-c++ devtoolset-3-binutils

scl enable devtoolset-3 bash

升级到gcc 5.2:

Copy

wget https://copr.fedoraproject.org/coprs/hhorak/devtoolset-4-rebuild-bootstrap/repo/epel-6/hhorak-devtoolset-4-rebuild-bootstrap-epel-6.repo -O /etc/yum.repos.d/devtoolset-4.repo

yum install devtoolset-4-gcc devtoolset-4-gcc-c++ devtoolset-4-binutils -y

scl enable devtoolset-4 bash

编译gRPC命令列工具

如果仅使用golang、java,请忽略本节。

gRPC分C、JAVA、GO、NodeJS版本,C版本包括C++, Python, Ruby, Objective-C, PHP, C#,这些语言都是基于C版本开发的,共用程式码库一个程式码库。

C版本:https://github.com/grpc/grpcJAVA版本:https://github.com/grpc/grpc-javaGO版本:https://github.com/grpc/grpc-goNode版本:https://github.com/grpc/grpc-node如果使用C版本的gRPC,最终要从源代码里编译出下列工具:

Copy

grpc_cpp_plugin

grpc_csharp_plugin

grpc_node_plugin

grpc_objective_c_plugin

grpc_php_plugin

grpc_python_plugin

grpc_ruby_plugin

这些工具作为外挂供proto编译器使用。需要先下载 grpc/grpc github上的源代码。

Copy

git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc

cd grpc

git submodule update --init

make && sudo make install

# 生成的外挂路径

ll ./bins/opt/

# 复制到bin目录

cp -r ./bins/opt/* /usr/local/bin/

这里有2个坑:

1、grpc/grpc仓库比较大,鉴于国内访问的网速,建议使用国内映象。码云(https://gitee.com)提供了同步更新的映象地址:

Copy

git clone https://gitee.com/mirrors/grpc-framework grpc

这样下载速度提高了不少。

2、git submodule update这个命令实际就是在下载.gitmodules档案里定义的第三方依赖项到third_party目录,这个依赖项有很多,大家可以开启.gitmodules档案检视下详情。依赖的仓库都在github上,下载没几个小时是下载不下来的,就等著慢慢下载吧。

回头想想,我们花费了很多时间,结果只是为了得到grpc的proto编译外挂。

福利:Mac下已编译完成的二进位制包:https://files.cnblogs.com/files/52fhy/bins.tar.gz 。下载以上档案解压,将bins/opt/里的所有档案复制到/usr/local/bin/。

PHP相关支援

如果仅使用golang、java,请忽略本节。

PHP暂时不支援作为grpc的服务端。作为客户端是可以的,需要机器安装:

protoc编译工具protobuf c扩充套件gRPC命令列工具(grpc_php_plugin)grpc c扩充套件grpc php库其中protoc和protobuf c扩充套件已经在 Protobuf 小试牛刀 介绍过了,这里不再赘述。上一小节里如果安装成功,那么grpc_php_plugin也是有了的。下面介绍如何安装PHP版的gRPC库。

安装grpc c扩充套件:

要求:GCC编译器需要4.8及以上版本。可以使用pecl安装:

Copy

pecl install grpc

也可以指定版本:

Copy

pecl install grpc-1.12.0

或者下载源代码(http://pecl.php.net/package/grpc)安装:

Copy

wget http://pecl.php.net/get/grpc-1.21.3.tgz

tar zxvf grpc-1.21.3.tgz && cd grpc-1.21.3

phpize

./configure

make

make install

grpc/grpc程式码库里也有PHP扩充套件的C源代码,在grpc/src/php/ext/grpc目录,进去也可以直接编译。

编译完成后在php.ini里新增,使用php --ri grpc可以检视资讯。

安装完C扩充套件后,还需要使用composer安装grpc的库:

Copy

composer require grpc/grpc

gRPC示例

编写gRPC proto

一共定义了三个档案:

Copy

└── proto

├── GreeterService.proto

├── Response.proto

└── User.proto

其中 User 作为 Model定义,Response 用于 RPC统一返回定义,GreeterService 则是服务界面定义。

限于篇幅,proto档案详见 https://github.com/52fhy/grpc-sample 仓库的proto目录。

GreeterService.proto档案内容如下:

Copy

syntax = "proto3";

package Sample.Model; //namesapce

import "User.proto";

import "Response.proto";

service Greeter {

// Sends a greeting

rpc SayHello (User) returns (Response) {}

}

这里面定义了一个service,相当于定义了一个服务界面,我们把方法名、引数定义好了,后面需要去实现它。由于gRPC不支援PHP作为服务端,这里我们使用Golang作为服务端。

首先需要使用proto工具编译出golang的程式码:

Copy

mkdir -p Pb_Go

#编译

cd proto

protoc --go_out=plugins=grpc:../Pb_Go/ *.proto

cd -

如果提示protoc-gen-go找不到,请根据文章介绍(https://www.cnblogs.com/52fhy/p/11106670.html#autoid-2-0-0)进行安装。

执行成功,会在 Pb_Go目录里生成Go程式码:

Copy

Pb_Go

├── GreeterService.pb.go

├── Response.pb.go

└── User.pb.go

如果需要生成PHP客户端的程式码,则需要使用grpc php的命令列工具grpc_php_plugin,前面小结如果执行成功,这个工具已经有了。然后:

Copy

out=output/php

mkdir -p $out

#编译

cd proto

protoc --php_out=../$out --grpc_out=../$out --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin *.proto

cd -

# 修改名称空间

cd $out

mv GPBMetadata Sample/Model/

find . -name \'*.php\' ! -name example.php -exec sed -i "" -e \'s#GPBMetadata#Sample\\Model\\GPBMetadata#g\' -e \'s#\\Sample\\Model\\GPBMetadata\\Google#\\GPBMetadata\\Google#g\' {} ;

上面是在Mac下操作的,命令和Linux有些不同。CentOS下gRPC编译工具未编译。

最终生成的档案:

Copy

├── output

│ └── php

│ └── Sample

│ └── Model

│ ├── GPBMetadata

│ │ ├── GreeterService.php

│ │ ├── Response.php

│ │ └── User.php

│ ├── GreeterClient.php

│ ├── Response.php

│ ├── User.php

│ └── UserList.php

注意:编译那里如果我们不加--grpc_out=../$out --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin,生成的PHP类是没有GreeterClient的。这个档案是gRPC编译工具自动生成的,用于连线gRPC服务端。

go编写服务

我们用Golang写服务端。上面虽然生成了Golang的部分程式码,但真正的服务还没有写呢。

main.go

首先我们新建个main.go,程式码不多,我直接贴出来:

Copy

package main

import (

"fmt"

"log"

"net"

"time"

pb "grpc-sample/Pb_Go"

"golang.org/x/net/context"

"google.golang.org/grpc"

)

const (

addr = ":50051"

)

// server is used to implement helloworld.GreeterServer.

type server struct{}

// SayHello implements helloworld.GreeterServer

func (s *server) SayHello(ctx context.Context, u *pb.User) (*pb.Response, error) {

return &pb.Response{ErrCode: 0, ErrMsg: "success", Data: map[string]string{"name": "Hello " + u.Name}}, nil

}

func main() {

lis, err := net.Listen("tcp", addr)

if err != nil {

log.Fatalf("failed to listen: %v", err)

}

fmt.Printf("%s server start at %s ", time.Now(), addr)

s := grpc.NewServer()

pb.RegisterGreeterServer(s, &server{})

s.Serve(lis)

}

然后就可以编译了。

有个大坑:go build main.go的时候会先下载go.mod里定义的依赖(依赖比较多,详情检视:https://github.com/52fhy/grpc-sample/blob/master/go.mod),其中下面这条非常慢,仓库太大了,虽然重定向到github:

Copy

replace google.golang.org/api => github.com/googleapis/google-api-go-client v0.6.1-0.20190616000641-99157d28da34

为了快速下载,我在码云上做了映象,地址:gitee.com/52fhy/google-api-go-client 。改了之后下载快多了。

编译成功后,生成了二进位制档案main。我们可以直接执行:

Copy

$ ./main

2019-06-30 17:16:07.752508 +0800 CST m=+0.028838467 server start at :50051

go test

为了测试我们写的服务是否正常,可以写测试用例:

test_client.go

Copy

package main

import (

"context"

"google.golang.org/grpc"

pb "grpc-sample/Pb_Go"

"testing"

)

func TestExec(t *testing.T) {

conn, err := grpc.Dial(":50051", grpc.WithInsecure())

if err != nil {

t.Errorf("dial error: %v ", err)

}

defer conn.Close()

// 例项化客户端

client := pb.NewGreeterClient(conn)

// 呼叫服务

user := pb.User{}

user.Id = 1

user.Name = "test"

result, err := client.SayHello(context.Background(), &user)

if err != nil {

t.Errorf("grpc error: %v ", err)

}

t.Logf("Recevied: %v ", result)

}

执行:

Copy

$ go test -v client_test.go

=== RUN TestExec

--- PASS: TestExec (0.01s)

client_test.go:29: Recevied: errMsg:"success" data:

PASS

ok command-line-arguments 0.021s

执行有点慢,感觉依赖的库多了。

php客户端

使用gRPC PHP客户端,确保你已经安装了:

protobuf c扩充套件grpc c扩充套件grpc php库示例:

client_test.php

Copy

2020-02-04 01:10:00

相关文章