grpc 的安装和使用

介绍

grpc 是 Google 在 2015 年 2 月底时发布的一款开源 RPC 框架,其源码是由 C 语言编写的。
按照 Google 的说法,grpc 是:A high performance, open source, general RPC framework that puts mobile and HTTP/2 first.
简单来说,它是一个高性能,开源,将移动和 HTTP/2 放在首位的通用的 RPC 框架.

由于它构建于 HTTP/2 标准,因此它有很多优秀的特点,主要如下:

  • bidirectional streaming
  • flow control
  • header compression
  • multiplexing requests over a single TCP connection

这些特性在移动设备上节约电池使用时间和数据使用,加速服务和运行在云上的web应用。

源码编译及安装

源码地址:https://github.com/grpc/grpc

  1. 安装依赖
  • 配置工具:build-essential, autoconf, libtool
  • 测试支持:libgflags-dev
  • 编译工具:clang, libc++-dev

Tip: when building, you may want to explicitly set the LIBTOOL and LIBTOOLIZE environment variables when running make to ensure the version installed by brew is being used:

$ LIBTOOL=glibtool LIBTOOLIZE=glibtoolize make

protoc
GRPC 默认使用 protobuf 作为消息格式,为 protoc 是 protobuf 协议的编译器,因此,在构建 GRPC 之前确保 protoc 已经安装。

注:gRpc 源码中的 Makefile 文件中会自动检测当前系统是否已经安装了 protoc,如果没有安装,那么就会自动从其项目中的第三方库源码目录中进行安装。

  1. 编译

执行下列命令进行编译构建和安装

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

注意到第一行命令是安装 release 分支中的版本,如果想安装最新的 master HEAD 上的版本,那么直接

$ git clone https://github.com/grpc/grpc

注意:
编译过程中可能会遇到 openssl1.1.0 与 老版本 openssl1.0.1不兼容的问题(grpc 使用的老版本 openssl1.0.1),也就是说,如果本机环境使用的是 openssl1.1.0,那么编译 grpc 时会出现报错,可以去 Google 中搜索解决方案。

  1. 编译完成后生成的文件

构建完成之后,想要知道生成了哪些文件,我们可以通过查看 .gitignore 文件来获知。

打开 .gitignore 文件,可以看到如下内容:

# C/C++ build outputs
.build/
bins
gens
libs
objs

根据注释含义可知,编译成功后会在根目录下新建上述目录,不同的目录包含了不同的文件,这里主要来看 libs, bins 这两个目录,
bins 目录中包含了所有编译构建后生成二进制程序文件。
查看 bins/opt/ 会发现,生成了下列二进制程序,它们都是 grpc 对各个语言默认插件的实现:

grpc_cpp_plugin
grpc_csharp_plugin
grpc_node_plugin
grpc_objective_c_plugin
grpc_php_plugin
grpc_python_plugin
grpc_ruby_plugin

libs 目录中则包含了动态库,静态库等文件。查看 `libs/opt/`` 可以看到以 libgrpc, libgrpc++ 等为前缀的许多静态和动态库文件,这里不一一列举:

libgpr.a
libgpr.so.4.0.0-dev
libgrpc.a
libgrpc++.a
libgrpc++.so.1.5.0-dev
libgrpc.so.4 -> libgrpc.so.4.0.0-dev
libgrpc.so.4.0.0-dev
pkgconfig/
...
  1. 安装

执行 make install 就会自动安装上述编译所生成的库及二进制程序。这一步非常简单,其实质只是把相应的文件拷贝的系统目录而已。
想要知道具体会安装哪些文件,查看 Makefile 即可。
安装内容相当的复杂,实际上,我们没有必要去了解每个细节,只要知道哪些主要文件会被安装,以及他们会被安装在哪个目录就可以了。

我在这里对整个安装过程做了一个总结,如下:

(1)要安装的文件
按照文件类型,我把要安装或者说拷贝到系统目录的文件主要有以下几个部分:

    1. grcp 的相关头文件
    1. 静态库,动态库
    1. 可执行文件 (也即以 _plugin 结尾的各语言的 grpc 插件)

(2) 安装至的目录 (默认 /usr/local

如果没有指定安装目录的 prefix,那么默认的 prefix 是 /usr/local。如果想使用其他 prefix 比如 /usr,那么可以编辑 Makefile 文件修改 prefix 变量。
或者 make install DISTDIR=/usr/local 。

It depends on the package. If the Makefile is generated by GNU autotools (./configure) you can usually set the target location like so:
./configure --prefix=/usr/local
If the Makefile is not generated by autotools, but distributed along with the software, simply open it up in an editor and change it. The install target directory is probably defined in a variable somewhere.

从上文可知,如果源码包没有提供 configure 配文件,最可靠的办法就是编辑 Makefile 文件来指定 prefix。

按照不同的类型区别,它们分别将安装在如下目录

(1)头文件
$prefix/include
注:源码文件通常会在 $prefix/src 中,但通常没有必要安装源码。

(2)静态库及动态库 (.a 文件,.so,.so.x.x 文件)
对不同语言的支持,会有不同的静态库及动态库文件。
$prefix/lib

(3) plugins,也就是二进制文件
$prefix/bin

(4) pkg-config 文件
$prefix/lib/pkg-config

(5)证书文件 certs
$prefix/share/grpc

比如,根证书文件为:
$prefix/share/grpc/roots.pem

GRPC 实例

这里编写一个 C++ 使用 GRPC 的实例来试验 GRPC 的使用。

官方的 grpc 源码中提供了示例,进入 examples/cpp/helloworld 目录,执行 make 来编译所提供的 cpp 例子(greeter_server.cc, greeter_client.cc, etc):

可能会出现如下错误提示:

$ g++ helloworld.pb.o helloworld.grpc.pb.o greeter_client.o -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl -o greeter_client
Package grpc++ was not found in the pkg-config search path.
Perhaps you should add the directory containing `grpc++.pc'
to the PKG_CONFIG_PATH environment variable
No package 'grpc++' found
Package grpc was not found in the pkg-config search path.
Perhaps you should add the directory containing `grpc.pc'
to the PKG_CONFIG_PATH environment variable
No package 'grpc' found
/usr/bin/ld: helloworld.pb.o: undefined reference to symbol '_ZN6google8protobuf8internal16RegisterAllTypesEPKNS0_8MetadataEi'
/usr/lib/libprotobuf.so.13: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make: *** [Makefile:42: greeter_client] Error 1

根据提示可知,执行 pkg-config --libs protobuf grpc++ grpc 出错了,因为 PKG_CONFIG_PATH 没有设置。

解决办法很简单,只需按如下设置该变量即可:

$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig

设置完成之后,执行 pkg-config --libs protobuf grpc++ grpc 就会显示如下结果:

-L/usr/local/lib -lprotobuf -pthread -lpthread -lgrpc++ -lgrpc

现在,在 examples/cpp/helloworld 目录执行 make 就成功了,执行结果如下:

$ protoc -I ../../protos --cpp_out=. ../../protos/helloworld.proto
$ g++ -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o helloworld.pb.o helloworld.pb.cc
$ protoc -I ../../protos --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ../../protos/helloworld.proto
$ g++ -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o helloworld.grpc.pb.o helloworld.grpc.pb.cc
$ g++ -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o greeter_client.o greeter_client.cc
$ g++ helloworld.pb.o helloworld.grpc.pb.o greeter_client.o -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl -o greeter_client
$ g++ -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o greeter_server.o greeter_server.cc
$ g++ helloworld.pb.o helloworld.grpc.pb.o greeter_server.o -L/usr/local/lib `pkg-config --libs protobuf grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl -o greeter_server

Makefile 中指定了,先执行 protoc 生成 --cpp_out--grpc_out 两类文件,均是 cpp 头文件,它们是:helloworld.pb.hhelloworld.grpc.pb.h
实际上,helloworld.pb.h 是定义 protobuf Message 类型相关的代码,而 helloworld.grpc.pb.h 头文件是定义 grpc Service 相关的代码

需要注意的是:在 cpp 中,这两部分内容是分开放在两个头文件中的,而用 grpc-go 生成的 Message 和 Service 代码则是在同一个 go 文件中。

编译好 greeter_client, greeter_server 等可执行程序之后,执行 ./greeter_client,会出现如下结果:

$ ./greeter_client
./greeter_client: error while loading shared libraries: libgrpc++.so.1: cannot open shared object file: No such file or directory
./greeter_client: error while loading shared libraries: libgrpc++_reflection.so.1: cannot open shared object file: No such file or directory

libgrpc++.so 是一个运行时库,上述错误显示,greeter_client 动态连接该库时没找到这个库,这个库的搜索目录是在 LD_LIBRARY_PATH环境变量中定义里的,因此如果没在这个目录中,那么就会找不到,如果已经在这个目录中,可以执行 sudo ldconfig -v 来更新 /etc/ld.so.conf 的 cache(也即 /etc/ld.so.cache 文件)。

由于安装时,所有的 libgrpc 相关的静态库和动态库都会安装在 /usr/local/lib 目录中,而这个目录已经加入 LD_LIBRARY_PATH 环境变量,经过查看发现,/usr/local/lib 目录中确实没有 libgrpc++.so.1,原因是什么呢?

原来,在 grpc 源码目录的构建生成的 libs/opt 目录下, libgrpc++.so.1 这个文件确实是存在的(它是一个 symlink 文件,真正指向的是 libgrpc++.so.1.5.0-dev)。
但是执行 make install 安装的时候,却变成了 libgrpc++.so.4,那就扯淡了。那么,最简单的解决办法就是把构建目录中的 libgrpc++.so.1 拷贝到 /usr/local/lib 中去。或者把 libgrpc++.so.4 改成 libgrpc++.so.1

最后执行

g++ -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o route_guide.grpc.pb.o route_guide.grpc.pb.cc
g++ -std=c++11 `pkg-config --cflags protobuf grpc`  -c -o route_guide_client.o route_guide_client.cc

全文完

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容