目标:
1.什么是GRPC服务?
2.安卓客户端怎么不熟GRPC服务?
3.怎么生成GRPC的java类?
一、什么是GRPC服务?
GRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
支持长连接。
在 GRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,GRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 GRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
特征一:多语言/跨平台
gRPC 客户端和服务端可以在多种环境中运行和交互 - 从 google 内部的服务器到你自己的笔记本,并且可以用任何 gRPC 支持的语言来编写。所以,你可以很容易地用 Java 创建一个 gRPC 服务端,用 Go、Python、Ruby 来创建客户端。此外,Google 最新 API 将有 gRPC 版本的接口,使你很容易地将 Google 的功能集成到你的应用里。
特征二:序列化:使用 protocol buffers
gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。
二、GRPC安装
需要使用GRPC服务,首先需要安装GRPC工具。
怎么安装GRPC工具呢?
2.1 GRPC安装
GPRC安装,最直接的访问官网,
https://grpc.io/docs/languages/cpp/quickstart/
以Mac OS为例。
2.1.1 安装依赖工具
2.1.1.1 安装cmake
编译需要安装cmake工具。
如果未安装cmake,则需要安装。已安装则进入下一步。
brew install cmake
可以通过以下指令查询本地cmake版本。
➜ local $ cmake --version
cmake version 3.22.1-g37088a8
CMake suite maintained and supported by Kitware (kitware.com/cmake).
2.1.1.2 安装其他依赖工具
Mac OS:
$ brew install autoconf automake libtool pkg-config
安装其他编译grpc项目需要的依赖工具。
Linux版本:
$ sudo apt install -y build-essential autoconf libtool pkg-config
安装bazel
可以参考官网
https://bazel.build/install?hl=zh-cn
$ brew install bazel
# 安装后可以确认版本
$ bazel --version
# 升级bazel
$ brew upgrade bazel
2.1.2 克隆项目
克隆grpc仓库以及submodules。
$ git clone --recurse-submodules -b v1.64.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
如果克隆报错:不能连接服务器,采用 ssh方式克隆。
Cloning into 'grpc'...
fatal: unable to access 'https://hub.fastgit.xyz/grpc/grpc/': Failed to connect to hub.fastgit.xyz port 443 after 75028 ms: Couldn't connect to server
$ git clone --recurse-submodules -b v1.64.0 --depth 1 --shallow-submodules git@github.com:grpc/grpc.git
使用ssh方式克隆记得先设置ssh-key。
克隆的时候,有third_party仓库项目克隆失败。
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
Submodule 'third_party/abseil-cpp' (https://github.com/abseil/abseil-cpp.git) registered for path 'third_party/abseil-cpp'
Submodule 'third_party/benchmark' (https://github.com/google/benchmark) registered for path 'third_party/benchmark'
Submodule 'third_party/bloaty' (https://github.com/google/bloaty.git) registered for path 'third_party/bloaty'
Submodule 'third_party/boringssl-with-bazel' (https://github.com/google/boringssl.git) registered for path 'third_party/boringssl-with-bazel'
Submodule 'third_party/cares/cares' (https://github.com/c-ares/c-ares.git) registered for path 'third_party/cares/cares'
Submodule 'third_party/envoy-api' (https://github.com/envoyproxy/data-plane-api.git) registered for path 'third_party/envoy-api'
Submodule 'third_party/googleapis' (https://github.com/googleapis/googleapis.git) registered for path 'third_party/googleapis'
Submodule 'third_party/googletest' (https://github.com/google/googletest.git) registered for path 'third_party/googletest'
Submodule 'third_party/opencensus-proto' (https://github.com/census-instrumentation/opencensus-proto.git) registered for path 'third_party/opencensus-proto'
Submodule 'third_party/opentelemetry' (https://github.com/open-telemetry/opentelemetry-proto.git) registered for path 'third_party/opentelemetry'
Submodule 'third_party/protobuf' (https://github.com/protocolbuffers/protobuf.git) registered for path 'third_party/protobuf'
Submodule 'third_party/protoc-gen-validate' (https://github.com/envoyproxy/protoc-gen-validate.git) registered for path 'third_party/protoc-gen-validate'
Submodule 'third_party/re2' (https://github.com/google/re2.git) registered for path 'third_party/re2'
Submodule 'third_party/xds' (https://github.com/cncf/xds.git) registered for path 'third_party/xds'
Submodule 'third_party/zlib' (https://github.com/madler/zlib) registered for path 'third_party/zlib'
怎么办呢?
查看submodules,在项目的.gitmodules可以查看这些第三方子模块
➜ grpc git:(v1.62.0) cat .gitmodules
[submodule "third_party/abseil-cpp"]
path = third_party/abseil-cpp
url = https://github.com/abseil/abseil-cpp.git
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/google/benchmark
[submodule "third_party/bloaty"]
path = third_party/bloaty
url = https://github.com/google/bloaty.git
[submodule "third_party/boringssl-with-bazel"]
path = third_party/boringssl-with-bazel
url = https://github.com/google/boringssl.git
[submodule "third_party/cares/cares"]
path = third_party/cares/cares
url = https://github.com/c-ares/c-ares.git
[submodule "third_party/envoy-api"]
path = third_party/envoy-api
url = https://github.com/envoyproxy/data-plane-api.git
[submodule "third_party/googleapis"]
path = third_party/googleapis
url = https://github.com/googleapis/googleapis.git
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest.git
[submodule "third_party/opencensus-proto"]
path = third_party/opencensus-proto
url = https://github.com/census-instrumentation/opencensus-proto.git
[submodule "third_party/opentelemetry"]
path = third_party/opentelemetry
url = https://github.com/open-telemetry/opentelemetry-proto.git
[submodule "third_party/protobuf"]
path = third_party/protobuf
url = https://github.com/protocolbuffers/protobuf.git
[submodule "third_party/protoc-gen-validate"]
path = third_party/protoc-gen-validate
url = https://github.com/envoyproxy/protoc-gen-validate.git
[submodule "third_party/re2"]
path = third_party/re2
url = https://github.com/google/re2.git
[submodule "third_party/xds"]
path = third_party/xds
url = https://github.com/cncf/xds.git
[submodule "third_party/zlib"]
path = third_party/zlib
url = https://github.com/madler/zlib
# When using CMake to build, the zlib submodule ends up with a
# generated file that makes Git consider the submodule dirty. This
# state can be ignored for day-to-day development on gRPC.
ignore = dirty
方法一:采用git更新子模块
git submodule update
第一次克隆失败,这个子模块git 更新大概率也会失败。
方法二:手动克隆
cd third_party
git clone git@github.com:abseil/abseil-cpp.git
git clone git@github.com:google/benchmark.git
git clone git@github.com:google/bloaty.git
git clone git@github.com:google/boringssl.git
2.1.3 编译项目
2.1.3.1 设置GPRC安装目录
编译项目,需要设置.
根据自己需要设置安装目录。例如:
export GRPC_INSTALL_DIR=/usr/local/grpc
export PATH="$GPRC_INSTALL_DIR/bin:$PATH"
2.1.3.2 编译和安装
$ cd grpc
# 创建编译目录
$ mkdir -p cmake/build
# 在路径之间自由切换
$ pushd cmake/build
# cmake环境配置
$ cmake -DgRPC_INSTALL=ON \
-DgRPC_BUILD_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX=$GRPC_INSTALL_DIR \
../..
$ make -j 4
$ sudo make install
$ popd
编译安装成功,添加环境变量
$ sudo vi /etc/zprofile
# 添加grpc的环境变量
export GRPC_HOME=/usr/local/grpc
export PATH=$PATH:$GRPC_HOME/bin
2.1.3.3 常见编译错误
1.编译错误cares未包含CmakeLists.txt文件
执行
cmake -DgRPC_INSTALL=ON \
-DgRPC_BUILD_TESTS=OFF \
-DCMAKE_INSTALL_PREFIX=$GRPC_INSTALL_DIR \
../..
报错。
-- Performing Test HAVE_STDC_FORMAT_MACROS - Success
CMake Warning at third_party/abseil-cpp/CMakeLists.txt:82 (message):
A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake
3.8 and up. We recommend enabling this option to ensure your project still
builds correctly.
-- Performing Test ABSL_INTERNAL_AT_LEAST_CXX17
-- Performing Test ABSL_INTERNAL_AT_LEAST_CXX17 - Failed
-- Performing Test ABSL_INTERNAL_AT_LEAST_CXX20
-- Performing Test ABSL_INTERNAL_AT_LEAST_CXX20 - Failed
CMake Error at cmake/cares.cmake:25 (add_subdirectory):
The source directory
/Users/a1/workspace/DEV/grpc/third_party/cares/cares
does not contain a CMakeLists.txt file.
Call Stack (most recent call first):
CMakeLists.txt:337 (include)
这个是cares项目的代码不全导致,同步一下cares.
$ cd third_party
$ cd cares
$ git pull origin master
因为cares/cares也是一个依赖submodule。
因此,需要进入克隆依赖项目下来
$ git clone git@github.com:c-ares/c-ares.git
$ rm cares
# 将项目重新命名为cares,保持和原目录定义一致
$ mv c-ares cares
然后重新编译。
2. ClassDataFull构造函数参数错误
Built target libprotobuf-lite失败。
[ 23%] Building CXX object CMakeFiles/gpr.dir/src/core/lib/gprpp/posix/env.cc.o
/Users/a1/workspace/DEV/grpc/third_party/protobuf/src/google/protobuf/any.pb.cc:180:21: error: no matching constructor for initialization of 'const ::google::protobuf::MessageLite::ClassDataFull'
ClassDataFull _data_ = {
^ ~
/Users/a1/workspace/DEV/grpc/third_party/protobuf/src/google/protobuf/message_lite.h:598:15: note: candidate constructor not viable: requires 4 arguments, but 5 were provided
constexpr ClassDataFull(ClassData base,
^
/Users/a1/workspace/DEV/grpc/third_party/protobuf/src/google/protobuf/message_lite.h:597:10: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 5 were provided
struct ClassDataFull : ClassData {
^
on.cc.o
[ 24%] Building CXX object third_party/protobuf/CMakeFiles/libprotobuf-lite.dir/src/google/protobuf/wire_format_lite.cc.o
[ 24%] Linking CXX static library libprotobuf-lite.a
[ 24%] Built target libprotobuf-lite
make: *** [all] Error 2
安装bazel工具,然后再编译。
还是存在错误。
/Users/a1/workspace/DEV/grpc/third_party/protobuf/src/google/protobuf/any.pb.cc:180:21: error: no matching constructor for initialization of 'const ::google::protobuf::MessageLite::ClassDataFull'
ClassDataFull _data_ = {
^ ~
/Users/a1/workspace/DEV/grpc/third_party/protobuf/src/google/protobuf/message_lite.h:598:15: note: candidate constructor not viable: requires 4 arguments, but 5 were provided
constexpr ClassDataFull(ClassData base,
ClassDataFull构造函数是4个参数,当前提供了5个参数。因此创建对象报错。
有两种方案:
1)直接修改代码
2)确认分支是否正确,是否在其他分支使用5个参数的构造函数。
3) 确认本地Protobuf版本。
建议使用方法3)。
这个错误提示是由于在编译 Protobuf 代码时遇到不匹配的构造函数。通常,这种错误与编译器不兼容或 Protobuf 库版本不匹配有关。以下是解决这个问题的一些方法:
1. 检查 Protobuf 版本
确保你正在使用的 Protobuf 版本与项目中其他部分兼容。不同版本的 Protobuf 可能有 API 不兼容的问题。
2. 更新或重新安装 Protobuf
如果你使用的是旧版本的 Protobuf,尝试更新到最新版本。你可以通过以下命令更新 Protobuf:
# For Linux/MacOS
brew install protobuf
brew upgrade protobuf
bash
3. openssl/ssl头文件找不到。
distributor.h:36:
In file included from /Users/a1/workspace/DEV/grpc/src/core/lib/security/security_connector/ssl_utils.h:42:
/Users/a1/workspace/DEV/grpc/src/core/tsi/ssl/key_logging/ssl_key_logging.h:23:10: fatal error: 'openssl/ssl.h' file not found
#include <openssl/ssl.h>
^~~~~~~~~~~~~~~
需要安装openssl
https://github.com/openssl/openssl
因为需要头文件,因此需要手动安装
# 克隆项目
$ git clone git@github.com:openssl/openssl.git
# 编译
$ cd openssl
$ ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl
$ make
# 安装
$ sudo make install
也可以直接下载压缩包。
$ curl -0 https://www.openssl.org/source/openssl-3.3.0.tar.gz
$ tar -xzf openssl-3.3.0.tar.gz
$ cd openssl-3.3.0
添加环境变量
$ sudo vi /etc/zprofile
# openssl
export OPENSSL_HOME=/usr/local/ssl
# openssl头文件路径添加
$ export CPATH=/usr/local/ssl/include:$CPATH
# path enviroment
export PATH=$PATH:$OPENSSL_HOME/bin
然后生效环境变量
source /etc/zprofile
再次编译。
4. 找不到X509_STORE_set_check_crl的定义
grpc/src/core/tsi/ssl_transport_security.cc:2399:9: error: use of undeclared identifier 'X509_STORE_set_check_crl'
/Users/a1/workspace/DEV/grpc/third_party/boringssl-with-bazel/include/openssl/x509.h:4772:77: note: passing argument to parameter 'ctx' here
OPENSSL_EXPORT STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx,
^
/Users/a1/workspace/DEV/grpc/src/core/tsi/ssl_transport_security.cc:2399:9: error: use of undeclared identifier 'X509_STORE_set_check_crl'
X509_STORE_set_check_crl(cert_store, CheckCrlPassthrough);
^
6 errors generated.
make[2]: *** [CMakeFiles/grpc.dir/src/core/tsi/ssl_transport_security.cc.o] Error 1
make[1]: *** [CMakeFiles/grpc.dir/all] Error 2
make: *** [all] Error 2
openssl版本的参数
$ openssl version
OpenSSL 3.3.0 9 Apr 2024 (Library: OpenSSL 3.3.0 9 Apr 2024)
如果版本低于3.0,可以安装更新版本。
$ brew install openssl@3
然后重新编译
$ make clean
$ make -j 4
5. /Users/a1/workspace/DEV/grpc/third_party/upb/upb/message/compat.c:29:7: error: unknown type name 'upb_Extension'
const upb_Extension* upb_Message_FindExtensionByNumber(const upb_Message* msg,
^
third_party中的udp有问题
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install upb
不能使用最新版的upd,需要按照以下步骤更新upd
steps below;
1. Update third_party/upb directory by running
- `export GRPC_ROOT=~/git/grpc`
- `wget https://github.com/protocolbuffers/protobuf/releases/download/v25.1/protobuf-25.1.zip`
- `rm -rf $GRPC_ROOT/third_party/upb`
- `unzip protobuf-25.1.zip -d /tmp/protobuf`
- `cp -r /tmp/protobuf/protobuf-25.1/upb $GRPC_ROOT/third_party/upb`
2. Update the dependency in `grpc_deps.bzl` to the same commit
3. Populate the bazel download mirror by running `bazel/update_mirror.sh`
4. Run `tools/buildgen/generate_projects.sh` to regenerate the generated files
5. Run `tools/codegen/core/gen_upb_api.sh` to regenerate upb files.
三、GPRC客户端接入
服务端定义好grpc的接口以后,提供xxx.proto 接口文档。
客户端需要将对应的接口文档,编译为本地语言的接口文档,例如 C++版本,Java版本,kotlin版本等。