ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Apache Thrift Java 教程实战:从编译运行到源码级原理剖析

Apache Thrift Java 教程实战:从编译运行到源码级原理剖析 后端微服务API设计【免费下载链接】thriftApache Thrift项目地址https://gitcode.com/gh_mirrors/thrift2/thrift点击查看免费下载本指南围绕 tutorial/java/README.md 展开完整讲解 Apache Thrift Java 教程的运行流程如何编译 Java 运行时库、如何通过 make/ant 一键启动服务端与客户端并深入剖析教程背后的 IDL 定义、生成的 Java 代码、TSimpleServer/TThreadPoolServer 服务模型以及 SSL 安全模式实现。读完本文你将能够独立编译并运行 Thrift Java 教程并理解一个完整的 Thrift 服务从.thrift定义到 Java 客户端/服务端联通的完整链路。一、教程概览你能从中学到什么Apache Thrift 仓库中的tutorial/目录是一个跨语言的教学示例而tutorial/java/是其 Java 实现由四类核心文件构成文件作用tutorial/tutorial.thrift教程主 IDL定义了Calculator服务、Work结构体、InvalidOperation异常、Operation枚举等tutorial/shared.thrift被 include 的共享 IDL定义SharedStruct结构与SharedService服务tutorial/java/src/JavaServer.java服务端入口同时启动普通9090 端口与 SSL9091 端口两个服务tutorial/java/src/JavaClient.java客户端入口通过参数simple/secure选择连接模式并调用 RPCtutorial/java/src/CalculatorHandler.java业务逻辑实现实现Calculator.Iface接口tutorial/java/build.xml 与 tutorial/java/Makefile.amAnt 与 Automake 两套构建脚本封装代码生成、编译与运行阅读源码可以看到教程刻意覆盖了 Thrift 的核心概念include引入共享定义、namespace指定生成代码包名、typedef类型别名、const常量、enum枚举、struct结构体、exception异常、service服务定义以及oneway单向调用修饰符。理解这一份 IDL就理解了 Thrift IDL 语法的大半。二、环境准备编译 Java 运行时库按照 tutorial/java/README.md 的说明运行教程前必须先编译 Thrift 的 Java 库。有两种等价方式# 方式一使用 make依赖 Automake 生成的 Makefile cd thrift/lib/java make # 方式二使用 Ant依赖 lib/java 下的 build.xml cd thrift/lib/java ant两种方式最终都会产出运行教程所需的libthrift*.jar。从 tutorial/java/build.xml 中可以看到教程构建脚本会从${thrift.java.dir}/build/libs目录即thrift/lib/java/build/libs收集libthrift*.jar排除test、javadoc、sources变体组成libs.classpath这是教程编译与运行所依赖的核心类库路径。此外教程编译还需要 Thrift 编译器thrift可执行文件位于可执行路径中。tutorial/tutorial.thrift 的注释明确说明“Before running this file, you will need to have installed the thrift compiler into /usr/local/bin.” 构建脚本generatetarget 中直接以../../compiler/cpp/thrift的相对路径调用编译器见 tutorial/java/build.xml 的generatetarget因此需要先编译生成compiler/cpp/thrift二进制否则--gen java -r ../tutorial.thrift这一步会因找不到编译器而失败。三、运行教程三种启动方式3.1 一键启动推荐在thrift/tutorial/java目录下执行make tutorialmake tutorial会依次执行all调用 ant compile与ant tutorial。从 tutorial/java/build.xml 的tutorialtarget 可以看出Ant 会并行执行启动JavaServerfork 模式超时 10000ms日志输出到build/log/tutorial.log等待 2 秒后依次以simple和secure参数运行JavaClient且客户端失败时failonerrortrue会直接使构建失败便于自动化验证。也就是说一次命令即可看到普通连接与 SSL 连接两条完整链路的运行结果。3.2 服务端 / 客户端分开启动也可以像 tutorial/java/README.md 中给出的那样分别启动服务端与客户端# 终端 1启动服务端 make tutorialserver # 终端 2启动客户端simple 模式 make tutorialclient对应的 Ant targettutorialserver/tutorialclient在 tutorial/java/build.xml 中定义。tutorialserver以 fork 方式运行JavaServertutorialclient则依次运行JavaClient simple与JavaClient secure。3.3 完全使用 Ant如果你不使用 Automake也可以直接跳过 make 层ant tutorialserver ant tutorialclient三种方式内部都会经过相同的 target 依赖链init→generate→resolve→compile最终编译生成代码与手写代码到build/目录。3.4 构建流程细节build.xml 中的关键 target 说明如下Target作用init创建build/、build/log/、build/lib/等目录generate调用../../compiler/cpp/thrift --gen java -r ../tutorial.thrift在gen-java/下生成 Java 代码resolve通过 Maven Ant Tasks 下载httpclient、jslint4java-ant、mime-util、javax.annotation-api等依赖到build/lib/仓库地址由 tutorial/java/build.properties 的mvn.repo指定为https://repo1.maven.org/maven2compile先编译gen-java/下的生成代码再编译src/下的手写代码tutorial打tutorial.jar并并行运行服务端与客户端tutorialserver/tutorialclient分别运行JavaServer/JavaClientclean删除build/、gen-java/、tutorial.jar在 Automake 体系中tutorial/java/Makefile.am 只是把这些 Ant target 包装成同名 make 目标tutorial、tutorialserver、tutorialclient同时提供clean-local、all-local、check-local等标准 Automake 钩子使教程能融入整个仓库的configure make构建体系。四、IDL 定义剖析tutorial.thrift 与 shared.thrift4.1 基础类型tutorial/tutorial.thrift 的注释完整列出了 Thrift 支持的基础类型bool布尔值一个字节i8byte有符号 8 位整数i16/i32/i64有符号 16 / 32 / 64 位整数double64 位浮点数string字符串binary二进制大对象字节数组mapt1,t2、listt1、sett1容器类型4.2 include 与 namespaceinclude shared.thrift namespace java tutorialinclude让 IDL 可以引用其他.thrift文件被引用对象通过文件名前缀访问例如shared.SharedStruct。namespace java tutorial则指定生成的 Java 类放入tutorial包tutorial/shared.thrift 相应声明namespace java shared使共享定义生成到shared包。这也是 JavaServer.java 中import tutorial.*; import shared.*;的来源。4.3 typedef、const、enumtypedef i32 MyInteger const i32 INT32CONSTANT 9853 const mapstring,string MAPCONSTANT {hello:world, goodnight:moon} enum Operation { ADD 1, SUBTRACT 2, MULTIPLY 3, DIVIDE 4 }枚举本质是 32 位整数未显式赋值时从 1 开始C 风格复杂常量如 map使用 JSON 记法书写。4.4 struct 与 exceptionstruct Work { 1: i32 num1 0, 2: i32 num2, 3: Operation op, 4: optional string comment, } exception InvalidOperation { 1: i32 whatOp, 2: string why }每个字段都有整数标识符、类型、符号名和可选默认值optional字段在未设置时不会出现在序列化输出中。exception语法与struct完全一致用于定义可抛出的业务异常。4.5 service 定义service Calculator extends shared.SharedService { void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), oneway void zip() }服务可以继承其他服务extends shared.SharedServiceCalculator因此继承了getStruct方法方法定义形如 C 代码返回类型 参数列表 可选的throws异常列表oneway修饰符表示客户端只发送请求、不等待任何响应oneway方法必须返回void对应 CalculatorHandler.java 中的zip()。五、服务端实现JavaServer 源码解析tutorial/java/src/JavaServer.java 展示了 Thrift Java 服务端最小可用的组装方式其流程分为三步第一步创建 Handler 与 Processorhandler new CalculatorHandler(); processor new Calculator.Processor(handler);Handler 承载业务逻辑Processor 则由 Thrift 编译器自动生成Calculator.Processor负责协议消息的解码分发。第二步组装普通simple服务TServerTransport serverTransport new TServerSocket(9090); TServer server new TSimpleServer(new Args(serverTransport).processor(processor)); server.serve();第三步组装 SSLsecure服务TSSLTransportParameters params new TSSLTransportParameters(); params.setKeyStore(../../lib/java/test/resources/.keystore, thrift, null, null); TServerTransport serverTransport TSSLTransportFactory.getServerSocket(9091, 0, null, params); TServer server new TSimpleServer(new Args(serverTransport).processor(processor)); server.serve();main方法将两个服务分别放入两个线程并行启动因此教程运行时 9090明文与 9091TLS两个端口会同时监听。源码注释中提供了两个重要变体多线程服务将TSimpleServer换成TThreadPoolServer代码中以注释形式给出new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor))即可获得线程池化的并发处理能力SSL 参数可走 JVM 系统属性不显式设置 keystore 时可改用-Djavax.net.ssl.keyStore.keystore -Djavax.net.ssl.keyStorePasswordthrift命令行参数由 JSSE 默认配置接管无需手动 open()TSSLTransportFactory.getServerSocket返回时底层 server socket 已经完成绑定直接serve()即可。5.1 Handler 业务实现tutorial/java/src/CalculatorHandler.java 实现了Calculator.Iface接口覆盖全部五个方法ping、add、calculate、getStruct、zip。其中calculate演示了异常抛出与结构体使用case DIVIDE: if (work.num2 0) { InvalidOperation io new InvalidOperation(); io.whatOp work.op.getValue(); io.why Cannot divide by 0; throw io; } val work.num1 / work.num2; break;Handler 内部用一个HashMapInteger, SharedStruct log充当内存日志calculate把每次计算结果写入日志getStruct则按 key 读取——这正好对应了服务继承SharedService.getStruct的场景让客户端可以验证跨服务继承的 RPC 调用。六、客户端实现JavaClient 源码解析tutorial/java/src/JavaClient.java 根据命令行参数选择连接方式if (args[0].contains(simple)) { transport new TSocket(localhost, 9090); transport.open(); } else { TSSLTransportParameters params new TSSLTransportParameters(); params.setTrustStore(../../lib/java/test/resources/.truststore, thrift, SunX509, JKS); transport TSSLTransportFactory.getClientSocket(localhost, 9091, 0, params); } TProtocol protocol new TBinaryProtocol(transport); Calculator.Client client new Calculator.Client(protocol); perform(client); transport.close();要点普通模式TSocket连接localhost:9090需显式open()SSL 模式客户端需要 TrustStore内含受信任的证书与公钥本例为自签名证书通过TSSLTransportFactory.getClientSocket获取传输对象注释明确指出“连接在工厂方法调用时即已建立无需再调用 open()”协议层统一使用TBinaryProtocol二进制协议封装传输层再以Calculator.Client包装协议对象即可直接调用 RPC 方法。perform方法完整演示了四种典型调用场景client.ping(); // 无参无返回 int sum client.add(1,1); // 简单参数返回 client.calculate(1, work); // 结构体参数 异常捕获 client.getStruct(1); // 继承自 SharedService 的方法其中calculate特意用除零DIVIDE、num20触发InvalidOperation异常并在客户端捕获打印io.why完整验证了throws异常的跨进程传输。七、运行预期与验证以make tutorial一键运行后预期输出大致为ping() 112 Invalid operation: Cannot divide by 0 15-105 Check log: 5服务端build/log/tutorial.log中会记录对应的ping()、add(1,1)、calculate(...)、getStruct(1)调用日志这些System.out.println来自 CalculatorHandler.java。同时由于 build.xml 中tutorialclient依次以simple与secure两个参数运行客户端一次构建即可验证明文与 SSL 两条链路均正常。八、常见问题排查现象可能原因与对策generate失败找不到 thrift 可执行文件尚未编译compiler/cpp/thrift或编译器不在tutorial/java/../../compiler/cpp/相对路径下先编译整个 Thrift 编译器libthrift*.jar找不到未先执行cd thrift/lib/java make或ant编译 Java 库build/libs目录为空客户端连接 9090/9091 被拒绝服务端未启动或已退出分开运行时先make tutorialserver再执行客户端SSL 模式握手失败.keystore/.truststore路径相对于tutorial/java目录为../../lib/java/test/resources/请确认文件存在且口令为thrift这两个密钥库由仓库提供用于教程自签名证书演示tutorialserver长时间无输出Ant target 以 fork 方式运行且日志重定向到build/log/tutorial.log服务端控制台输出请查看该日志文件九、更进一步从教程走向生产教程只是起点build.xml 中注释掉的TThreadPoolServer就是向生产演进的第一步。在此基础上你可以沿着以下方向深入当前仓库阅读 lib/java/README.md 与 lib/java/src 下的 Java 库源码了解TTransport、TProtocol、TServer的完整继承体系与更多协议实现如TCompactProtocol、TJSONProtocol参考 test/ThriftTest.thrift 与 lib/java/src 中的测试用例覆盖更多类型与边界场景查看 tutorial/ 下其他语言C、Python、Go、Node.js 等的同名教程验证跨语言互操作——这正是 Thrift 的核心价值所在。本文所有命令与配置均以当前仓库实际内容为准运行前请确保已完成 Thrift 编译器与 Java 库的编译并具备 JDK 与 Ant或 Automake 工具链环境。赞分享后端微服务API设计【免费下载链接】thriftApache Thrift项目地址https://gitcode.com/gh_mirrors/thrift2/thrift点击查看免费下载相关推荐Apache Thrift Java 实战教程编译 Java 运行时库并运行 Tutorial 客户端与服务端Apache Thrift Java 实战教程编译 Java 运行时库并运行 Tutorial 客户端与服务端 Apache Thrift 官方仓库在 tut后端RPC框架序列化代码生成Gitskarios 项目常见问题解决方案Gitskarios 项目常见问题解决方案 项目基础介绍 Gitskarios 是一个用于访问 GitHub 的 Android 应用程序。它允许用户查看个人资RedwoodJS Cells 完全指南从教程实战到源码级原理剖析RedwoodJS Cells 完全指南从教程实战到源码级原理剖析 Cells 是 RedwoodJS 最具标志性的数据获取抽象你只需按约定导出 QUERY后端前端Web框架开发工具上一篇开发者必读Expert Kit模块详解与贡献指南下一篇深入xMIG源代码Rust实现的高性能故障拦截机制分析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表