因为gRPC主要是谷歌开发的,因为一些已知的缘由,gRPC跑demo仍是不那么顺利的。单独写这一篇,主要是gRPC安装过程当中的坑太多了,记录下来让你们少走弯路。php
主要的坑:html
go mod
增长映射规则到github仓库,github下载也是龟速。本文讲解gRPC demo的同时,会介绍如何解决这些坑。本文对应的Github地址:https://github.com/52fhy/grpc... 。该仓库存储了demo示例,以及部分系统编译好的二进制包,你们以为有些步骤里耗时实在太长了,能够直接clone该仓库,复制二进制包到对应目录(仅限测试开发,生产环境仍是老老实实本身编译吧)。java
gRPC命令行工具编译须要使用 GCC4.8及以上版本。CentOS6系列的内置版本是GCC4.7。node
使用
gcc --version
能够查看版本。
若是你的系统GCC版本>=4.8,能够忽略本节。若是仅使用golang、java,请忽略本节。python
注:不建议你们下载GCC源码包或者使用yum下载GCC4.8及以上版本,缘由:
1) 源码包安装真的是很是很是的慢 2) yum 源下载速度慢的像蜗牛。下面的SCL安装方法是推荐你们用的,安装好后原来的版本还能用。
若是须要升级gcc至4.8或更高版本,建议直接采用安装SCL
源以后安装devtoolset-6
(devtoolset-6目前gcc版本为6.3),由于devtoolset-4
及以前的版本都已经结束支持,只能经过其余方法安装。c++
升级到gcc 6.3:git
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的话:github
echo "source /opt/rh/devtoolset-6/enable" >>/etc/profile
这样退出shell从新打开就是新版的gcc了。其它版本同理。 golang
升级到gcc 7.3:shell
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:
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:
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:
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
若是仅使用golang、java,请忽略本节。
gRPC分C、JAVA、GO、NodeJS版本,C版本包括C++, Python, Ruby, Objective-C, PHP, C#,这些语言都是基于C版本开发的,共用代码库一个代码库。
若是使用C版本的gRPC,最终要从源码里编译出下列工具:
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上的源码。
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个坑:
一、grpc/grpc
仓库比较大,鉴于国内访问的网速,建议使用国内镜像。码云(https://gitee.com)提供了同步更新的镜像地址:
git clone https://gitee.com/mirrors/grpc-framework grpc
这样下载速度提升了很多。
二、git submodule update
这个命令实际就是在下载.gitmodules
文件里定义的第三方依赖项到third_party目录,这个依赖项有不少,你们能够打开.gitmodules
文件查看下详情。依赖的仓库都在github上,下载没几个小时是下载不下来的,就等着慢慢下载吧。
回头想一想,咱们花费了不少时间,结果只是为了获得grpc的proto编译插件。
福利:Mac下已编译完成的二进制包: https://files.cnblogs.com/fil... 。下载以上文件解压,将bins/opt/
里的全部文件复制到/usr/local/bin/
。
若是仅使用golang、java,请忽略本节。
PHP暂时不支持做为grpc的服务端。做为客户端是能够的,须要机器安装:
其中protoc
和protobuf c扩展
已经在 Protobuf 小试牛刀 介绍过了,这里再也不赘述。上一小节里若是安装成功,那么grpc_php_plugin
也是有了的。下面介绍如何安装PHP版的gRPC库。
安装grpc c扩展:
要求:GCC编译器须要4.8及以上版本。可使用pecl安装:
pecl install grpc
也能够指定版本:
pecl install grpc-1.12.0
或者下载源码(http://pecl.php.net/package/grpc)安装:
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的库:
composer require grpc/grpc
一共定义了三个文件:
└── proto ├── GreeterService.proto ├── Response.proto └── User.proto
其中 User
做为 Model定义,Response
用于 RPC统一返回定义,GreeterService
则是服务接口定义。
限于篇幅,proto文件详见 https://github.com/52fhy/grpc... 仓库的proto
目录。
GreeterService.proto
文件内容以下:
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的代码:
mkdir -p Pb_Go #编译 cd proto protoc --go_out=plugins=grpc:../Pb_Go/ *.proto cd -
若是提示
protoc-gen-go
找不到,请根据文章介绍(
https://www.cnblogs.com/52fhy...)进行安装。
执行成功,会在 Pb_Go
目录里生成Go代码:
Pb_Go ├── GreeterService.pb.go ├── Response.pb.go └── User.pb.go
若是须要生成PHP客户端的代码,则须要使用grpc php的命令行工具grpc_php_plugin
,前面小结若是执行成功,这个工具已经有了。而后:
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编译工具未编译。
最终生成的文件:
├── 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服务端。
咱们用Golang写服务端。上面虽然生成了Golang的部分代码,但真正的服务尚未写呢。
首先咱们新建个main.go,代码很少,我直接贴出来:
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\n", time.Now(), addr) s := grpc.NewServer() pb.RegisterGreeterServer(s, &server{}) s.Serve(lis) }
而后就能够编译了。
有个大坑:go build main.go
的时候会先下载go.mod
里定义的依赖(依赖比较多,详情查看:https://github.com/52fhy/grpc...),其中下面这条很是慢,仓库太大了,虽然重定向到github:
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
。咱们能够直接运行:
$ ./main 2019-06-30 17:16:07.752508 +0800 CST m=+0.028838467 server start at :50051
为了测试咱们写的服务是否正常,能够写测试用例: test_client.go
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\n", 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\n", err) } t.Logf("Recevied: %v\n", result) }
运行:
$ go test -v client_test.go === RUN TestExec --- PASS: TestExec (0.01s) client_test.go:29: Recevied: errMsg:"success" data:<key:"name" value:"Hello test" > PASS ok command-line-arguments 0.021s
运行有点慢,感受依赖的库多了。
使用gRPC PHP客户端,确保你已经安装了:
示例: client_test.php
<?php use Grpc\ChannelCredentials; use Sample\Model\User; use Sample\Model\UserList; use Sample\Model\GreeterClient; ini_set("display_errors", true); error_reporting(E_ALL); require_once "autoload.php"; $user = new User(); $user->setId(1)->setName("test"); $client = new GreeterClient("192.168.99.1:50051", [ 'credentials' => ChannelCredentials::createInsecure(), //不加密 // 'timeout' => 3000000, ]); //分别是响应、状态对象 list($reply, $status) = $client->SayHello($user)->wait(); if (!$reply) { echo json_encode($status); return; } //序列化为string echo $reply->serializeToJsonString(true) . PHP_EOL; echo $reply->getErrCode() . PHP_EOL; //errCode echo $reply->getErrMsg() . PHP_EOL; //errMsg //data foreach ($reply->getData() as $key => $value) { echo $key . "-" . $value . PHP_EOL; }
运行后输出:
$ php tests/client_test.php {"errMsg":"success","data":{"name":"Hello test"}} 0 success name-Hello test
一、CentOS6使用 go mod获取第三方依赖包unknown revision xxx错误
解决:其实go mod调用链中会用到一些git指令,当git版本比较旧时,调用失败产生错误,并给出歧义的提示信息。方法就是升级git版本,CentOS6自带的git是1.7版本。升级完毕后,再尝试go mod。
快速升级方法:
centos6:
# 安装yum源 wget http://opensource.wandisco.com/centos/6/git/x86_64/wandisco-git-release-6-1.noarch.rpm && rpm -ivh wandisco-git-release-6-1.noarch.rpm ## 安装git 2.x yum install git -y ## 验证 git --version git version 2.14.1
二、PHP报错:Fatal error: Class 'GoogleProtobufInternalMessage' not found
解决:请安装PHP的protobuf c扩展。
三、PHP报错:Fatal error: Class 'GrpcBaseStub' not found
解决:使用composer require grpc/grpc
安装grpc。另外对应的grpc C扩展也要安装。
四、下载 github release包很慢怎么办?
解决:下载Mac版 Free Download Manager
下载工具能够解决Github 下载缓慢或失败问题。速度嗖嗖的。
一、为CentOS 六、7升级gcc至4.八、4.九、5.二、6.三、7.3等高版本
http://www.vpser.net/manage/c...
二、centos 6.x/7.x使用yum升级git版本 - 夜空
https://blog.slogra.com/post-...
三、Protobuf 小试牛刀 - 飞鸿影
https://www.cnblogs.com/52fhy...