Apache Arrow C 之 Arrow Flight RPC 系统构建配置与开发运行指南【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrowApache Arrow 的 Arrow Flight 是一个基于 gRPC 构建的高性能 RPC 框架专为在分布式环境中以列式内存格式高效传输 Arrow 数据而设计。本文以仓库中cpp/src/arrow/flight/README.md的开发笔记为骨架结合 C 源码、构建脚本与协议定义系统讲解 Arrow Flight 的构建开关、protoc/gRPC 插件依赖、动态库搜索路径配置以及单元测试与测试服务器的运行方式帮助你在本地从零搭建可编译、可测试的 Arrow Flight C 开发环境。Arrow Flight 在 Arrow 项目中的位置Arrow Flight 是 Apache Arrow 生态中负责数据传输的 RPC 子系统。与传统的序列化-反序列化传输方式不同Flight 直接基于 Arrow 列式内存格式设计减少数据在网络边界上的复制与转换开销。在仓库中Flight 的核心代码集中在三个层面协议定义format/Flight.proto 定义了 Flight 服务的 gRPC 接口与消息结构是整个 Flight 系统的规范基石C 实现cpp/src/arrow/flight 提供了客户端、服务端、认证、中间件middleware、传输层transport等完整实现扩展模块cpp/src/arrow/flight/sql 提供 Flight SQL 扩展cpp/src/arrow/flight/integration_tests 则用于跨语言实现的一致性集成测试。从源码结构看Flight 的实现被刻意拆分为协议无关的核心层client.cc、server.cc、types.cc等与 gRPC 专用传输层transport/grpc/下的grpc_client.cc、grpc_server.cc、protocol_grpc_internal.cc等这为将来支持更多底层传输协议预留了扩展点。构建前提gRPC、Protocol Buffers 与 CMake 开关Flight 依赖 gRPC 与 Protocol Buffers 两大第三方库。仓库的 CMake 构建系统中通过选项控制是否编译 Flight见 cpp/cmake_modules/DefineOptions.cmakedefine_option(ARROW_FLIGHT Build the Arrow Flight RPC System (requires GRPC, Protocol Buffers) OFF DEPENDS ARROW_IPC) define_option(ARROW_FLIGHT_SQL Build the Arrow Flight SQL extension OFF DEPENDS ARROW_FLIGHT)要点如下选项默认值依赖说明ARROW_FLIGHTOFFARROW_IPC构建 Arrow Flight RPC 系统需要 gRPC 与 Protocol BuffersARROW_FLIGHT_SQLOFFARROW_FLIGHT构建 Flight SQL 扩展ARROW_FLIGHT_SQL_ODBCOFFARROW_FLIGHT_SQL、ARROW_COMPUTE构建 Flight SQL 的 ODBC 驱动ARROW_FLIGHT_SQL_ODBC_INSTALLEROFFARROW_FLIGHT_SQL_ODBC构建 ODBC 驱动安装器因此开启 Flight 的最小 CMake 配置形如cmake -DARROW_FLIGHTON \ -DARROW_IPCON \ -DARROW_BUILD_TESTSON \ ..CI 构建脚本 ci/scripts/cpp_build.sh 也印证了这些选项的用法脚本把ARROW_FLIGHT、ARROW_FLIGHT_SQL等环境变量逐一映射为-DARROW_FLIGHT...形式的 CMake 参数。值得注意的是该脚本在第 69~81 行明确规定当ARROW_ENABLE_THREADING为OFF时ARROW_FLIGHT及其 SQL/ODBC 系列选项会被强制置为OFF——这说明 Flight 的构建隐式依赖线程模型排查编译问题时值得留意。开发笔记之一libprotoc 的 LD_LIBRARY_PATH 问题cpp/src/arrow/flight/README.md第一条开发笔记明确指出The gRPC protobuf plugin requires that libprotoc is in yourLD_LIBRARY_PATH. Until we figure out a general solution, you may need to do:export LD_LIBRARY_PATH$PROTOBUF_HOME/lib:$LD_LIBRARY_PATH这条笔记的背景是Flight 的协议代码并非手写而是由 protoc 与 gRPC C 插件在构建期自动生成。从 cpp/src/arrow/flight/CMakeLists.txt 可以看到完整的生成逻辑set(FLIGHT_PROTO_PATH ${ARROW_SOURCE_DIR}/../format) set(FLIGHT_PROTO ${ARROW_SOURCE_DIR}/../format/Flight.proto) set(FLIGHT_PROTOBUF_COMMAND ... ) add_custom_command(OUTPUT ${FLIGHT_GENERATED_PROTO_FILES} DEPENDS ${PROTO_DEPENDS} ARGS COMMAND ${FLIGHT_PROTOC_COMMAND} --cpp_out${CMAKE_CURRENT_BINARY_DIR} ${FLIGHT_PROTO} COMMAND ${FLIGHT_PROTOC_COMMAND} --grpc_out${CMAKE_CURRENT_BINARY_DIR} --pluginprotoc-gen-grpc$TARGET_FILE:gRPC::grpc_cpp_plugin ${FLIGHT_PROTO})也就是说构建过程会以format/Flight.proto为输入先后执行两次 protoc--cpp_out...生成Flight.pb.cc/Flight.pb.hProtocol Buffers 消息代码--grpc_out...配合protoc-gen-grpc插件生成Flight.grpc.pb.cc/Flight.grpc.pb.hgRPC 服务桩代码。protoc-gen-grpc作为动态加载的插件运行期需要定位libprotoc动态库因此当 protobuf 安装在非系统默认路径例如$PROTOBUF_HOME时必须先把其lib目录加入LD_LIBRARY_PATH否则构建期会报找不到共享库的错误。这正是 README 中那条export命令存在的意义。若使用仓库自带的 vendored protobufCMakeLists.txt 还会额外追加 protobuf 的 include 目录以保证Flight.proto中引用的google/protobuf/timestamp.proto等 well-known 类型可以被找到if(PROTOBUF_VENDORED AND Protobuf_INCLUDE_DIRS) list(APPEND FLIGHT_PROTOC_COMMAND -I${Protobuf_INCLUDE_DIRS}) endif()一个小细节Protobuf 3.15 之前的兼容开关同一个文件中还有一处历史兼容逻辑当Protobuf_VERSION小于 3.15 时protoc 需要显式加上--experimental_allow_proto3_optional才能解析Flight.proto中optional double progress这类 proto3 optional 字段见 format/Flight.proto。CMake 已自动处理开发者无需手动干预。开发笔记之二运行单元测试的 PATH 配置README 的第二条开发笔记说明了测试可执行文件的运行方式Currently, to run the unit tests, the directory of executables must either be your current working directory or you need to add it to your path, e.g.PATHdebug:$PATH debug/flight-test这条笔记的背景与 Flight 测试的运行机制有关。从 cpp/src/arrow/flight/CMakeLists.txt 可以看到Flight 的测试目标包括flight_internals_test内部机制测试flight_internals_test.ccflight_test端到端功能测试flight_test.ccflight-test-server供单元测试或基准测试使用的独立测试服务器可执行文件由test_server.cc编译而来。flight_test等测试在运行时会拉起flight-test-server作为对端。README 中PATHdebug:$PATH debug/flight-test的写法意味着测试程序会通过进程名而非绝对路径去查找flight-test-server因此要么把可执行文件所在目录设为当前工作目录要么把它加入PATH。debug只是示例中的构建输出目录名实际构建目录如release、build等需要按你的 CMake 配置替换。此外若使用静态链接的 protobuf/gRPCCMake 会强制要求 Arrow 也静态构建见 CMakeLists.txt并在链接测试时选择arrow_flight_static、arrow_flight_testing_staticif(ARROW_FLIGHT_TEST_LINKAGE STREQUAL static) if(NOT ARROW_BUILD_STATIC) message(FATAL_ERROR Must build Arrow statically to link Flight tests statically) endif() set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_static arrow_flight_testing_static)原因是 protobuf/gRPC 带有全局状态静态/动态链接方式必须保持一致否则会出现难以排查的链接期或运行期错误。这一约束在排查测试链接失败时非常关键。从协议到 APIFlight 的 RPC 全景为了理解上述构建产物到底生成了什么有必要看一眼 Flight 协议本体。Flight.proto定义的FlightService共包含 9 个 RPC见 format/Flight.protoRPC方向用途Handshake双向流客户端与服务端握手协商认证 tokenListFlights服务端流按Criteria列出可用的数据流GetFlightInfo普通给定FlightDescriptor返回数据访问计划FlightInfoPollFlightInfo普通长查询场景下轮询执行状态可边执行边取结果GetSchema普通获取数据流对应的 SchemaDoGet服务端流凭Ticket拉取单个数据流批量下行DoPut客户端流向服务端上传数据流批量上行DoExchange双向流双向交换任意 Arrow 数据与应用元数据适合计算卸载DoAction/ListActions服务端流执行/列举服务自定义动作其中DoGet/DoPut是数据搬运的主干DoExchange则更贴近把计算交给 Flight 服务的场景Flight.proto 注释明确说明这一点。围绕这些 RPC协议还定义了FlightInfo含endpoint列表、total_records/total_bytes、ordered标志与app_metadata见 Flight.proto、PollInfo长查询进度与重试描述符Flight.proto、Ticket单次使用的流令牌Flight.proto与Location支持grpc://、grpctls://乃至 HTTP 直取 URL 的多种位置表达Flight.proto等消息。这些 RPC 在 C 侧分别映射为FlightClient与FlightServerBase上的方法。客户端 API 定义在 cpp/src/arrow/flight/client.hFlightClient::Connect(location, options)建立连接注意注释强调返回 OK 并不代表连接一定成功FlightClient::GetFlightInfo(descriptor)/DoGet(ticket)/DoPut(stream)对应核心数据操作FlightClient::Authenticate/AuthenticateBasicToken认证入口FlightClient::ListActions/DoAction动作枚举与执行FlightClient::CancelFlightInfo/RenewFlightEndpoint长查询取消与端点续期。客户端配置FlightClientOptionsclient.h还暴露了tls_root_certsTLS 根证书、cert_chain/private_key双向 TLS 客户端证书、write_size_limit_bytes单批写入软上限用于保护服务端内存、disable_server_verification等生产级选项而FlightCallOptionsclient.h则提供单次调用的timeout、自定义headers、stop_token取消令牌与memory_manager内存控制。服务端侧cpp/src/arrow/flight/server.h 的FlightDataStream接口负责把 RecordBatch 序列化为FlightData消息流RecordBatchStream是其开箱即用的基础实现。构建与测试的完整实操流程综合 README 与仓库脚本一个可复现的本地开发流程如下1. 准备依赖与动态库路径确保系统已安装 gRPC 与 Protocol Buffers版本要求可参考仓库的 CMake 检测逻辑。若 protobuf 装在自定义前缀$PROTOBUF_HOME下先导出动态库路径export LD_LIBRARY_PATH$PROTOBUF_HOME/lib:$LD_LIBRARY_PATH2. 配置并编译cmake -S cpp -B build \ -DARROW_FLIGHTON \ -DARROW_IPCON \ -DARROW_BUILD_TESTSON \ -DARROW_BUILD_BENCHMARKSON cmake --build build --target flight-test-server arrow-flight-benchmark -j$(nproc)构建产物中Flight.pb.*与Flight.grpc.pb.*由 CMake 的flight_grpc_gen自定义目标自动生成flight-test-server供测试使用arrow-flight-perf-server与arrow-flight-benchmark则用于性能基准见 CMakeLists.txt基准协议定义在同目录的perf.proto。3. 运行单元测试将构建目录加入PATH后再执行测试build换成你的实际构建目录PATHbuild:$PATH build/flight-test PATHbuild:$PATH build/flight-internals-testflight_test.cc、flight_internals_test.cc位于 cpp/src/arrow/flight覆盖客户端-服务端往返、认证、中间件、Cookie 管理等场景需要更完整测试集时还可使用 cpp/src/arrow/flight/test_server.cc 对应的flight-test-server配合 cpp/src/arrow/flight/integration_tests 做跨语言集成验证。4. 深入扩展Flight SQL 与跨语言绑定若业务需要 SQL 语义可在上述基础上追加-DARROW_FLIGHT_SQLON构建 cpp/src/arrow/flight/sql 中的客户端/服务端扩展该目录下还包含基于 SQLite 的示例服务sql/example/sqlite_server.cc。对于使用 GLib 绑定或 Ruby 绑定的场景c_glib/arrow-flight-glib与ruby/red-arrow-flight提供了相应的语言封装可作为交叉验证 Flight 协议一致性的参考。小结Arrow Flight 的 C 开发环境搭建核心在于三件事用-DARROW_FLIGHTON打开构建开关、为 gRPC protobuf 插件正确配置LD_LIBRARY_PATH、以及把测试可执行文件目录加入PATH。这三条经验全部源自 cpp/src/arrow/flight/README.md 的开发笔记而其背后的机制——Flight.proto的代码生成流程、静态链接约束、测试服务器的进程查找方式——都能在 cpp/src/arrow/flight/CMakeLists.txt、format/Flight.proto 与 cpp/cmake_modules/DefineOptions.cmake 中找到一一对应的实现证据。掌握这些细节你就具备了在本地编译、测试并二次开发 Arrow Flight C 客户端的完整能力。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考