Ubuntu 22.04 安装 Apache Thrift 指南
在 Ubuntu 22.04 从官方源码编译安装 Apache Thrift 0.25.0 编译器、C++ 与 Python3 运行时,集成 Java libthrift,覆盖依赖安装、configure 裁剪、编译安装、验证与卸载全流程。
Ubuntu 22.04 安装 Apache Thrift 指南
一、环境信息
本文以一台全新 Ubuntu 22.04 服务器为例,从官方源码包编译安装 Apache Thrift IDL 编译器、C++ 运行时库与 Python3 运行时,并完成 Java 运行时(libthrift)的 Maven 集成与最小 RPC 验证。所有命令与回显均在真实环境实测采集。
| 项目 | 说明 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS(x86_64) |
| Thrift 版本 | 0.25.0(官方当前最新稳定版,2026-09-30 发布) |
| C/C++ 编译器 | g++ 11.4.0(仓库默认版本) |
| JDK | OpenJDK 17.0.20.1(openjdk-17-jdk) |
| Maven | 3.6.3(apt 仓库版本) |
| Python | Python 3.10(系统自带,需补 setuptools 与 pip) |
| 安装前缀 | /opt/thrift |
| 执行账号 | root |
二、前置条件
2.1 更新索引并安装基础工具
以 root 账号登录服务器,先确保 curl 可用(最小化安装默认缺失):
apt-get update
apt-get install -y curl ca-certificates
2.2 安装 JDK 17 与 Maven
apt-get install -y openjdk-17-jdk maven
java -version
mvn -version | head -3
实测回显:
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 17.0.20.1, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
三、版本选型说明
| 事项 | 说明 |
|---|---|
| 最新稳定版 | 访问 https://downloads.apache.org/thrift/ 确认,截至本文实测为 0.25.0 |
| 源码包 | thrift-0.25.0.tar.gz,约 4.9 MB |
| 完整性校验 | 同目录下 thrift-0.25.0.tar.gz.sha256 提供官方摘要 |
| 历史版本 | archive.apache.org/dist/thrift/ 保留全部历史版本 |
| Java 运行时坐标 | org.apache.thrift:libthrift,版本号需与编译器版本一致 |
说明:--with-java 配置项控制的是「是否随源码树编译 Java 运行时库」,与编译器能否生成 Java 代码无关,Java 代码生成器内置于 thrift 编译器本体。生产实践推荐:编译器从源码安装,Java 运行时统一通过 Maven Central 引入 libthrift,二者版本保持一致即可,因此本文 configure 阶段将 Java 库源码构建裁剪掉。
四、安装步骤
4.1 安装编译依赖
apt-get install -y automake autoconf bison flex g++ libboost-all-dev libevent-dev libssl-dev libtool make pkg-config python3-dev
依赖用途:g++ 编译编译器本体与 C++ 库;bison/flex 生成 IDL 语法解析器;libssl-dev 提供 TLS 支持;libevent-dev 支持非阻塞服务端;libboost-all-dev 为 C++ 库必需;python3-dev 供 Python3 绑定使用。
4.2 下载源码包并校验
mkdir -p /opt/src && cd /opt/src
curl -fLO https://downloads.apache.org/thrift/0.25.0/thrift-0.25.0.tar.gz
sha256sum thrift-0.25.0.tar.gz
curl -sO https://downloads.apache.org/thrift/0.25.0/thrift-0.25.0.tar.gz.sha256
cat thrift-0.25.0.tar.gz.sha256
实测回显:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 4949k 100 4949k 0 0 2526k 0 0:00:01 0:00:01 --:--:-- 2526k
66da4707214c54c94bac082103dc67adaf9e08925662700f269170a7b534b214 thrift-0.25.0.tar.gz
66da4707214c54c94bac082103dc67adaf9e08925662700f269170a7b534b214 thrift-0.25.0.tar.gz.sha256
本地计算值与官方摘要一致方可继续。
4.3 解压并执行 configure
tar -xzf thrift-0.25.0.tar.gz
cd thrift-0.25.0
./configure --prefix=/opt/thrift --with-cpp --with-py3 --without-python --disable-tests --disable-tutorial --without-qt5 --without-c_glib --without-java --without-kotlin --without-erlang --without-nodejs --without-nodets --without-lua --without-perl --without-php --without-php_extension --without-dart --without-ruby --without-go --without-rs --without-cl --without-haxe --without-netstd --without-d
configure 结束后输出能力摘要,实测回显(节选):
thrift 0.25.0
Building C (GLib) Library .... : no
Building C++ Library ......... : yes
Building Common Lisp Library.. : no
Building D Library ........... : no
Building Dart Library ........ : no
Building .NET Standard Library : no
Building Erlang Library ...... : no
Building Go Library .......... : no
Building Haxe Library ........ : no
Building Java Library ........ : no
Building Kotlin Library ...... : no
Building Lua Library ......... : no
Building NodeJS Library ...... : no
Building Perl Library ........ : no
Building PHP Library ......... : no
Building Python Library ...... : no
Building Py3 Library ......... : yes
Building Ruby Library ........ : no
Building Rust Library ........ : no
C++ Library:
C++ compiler .............. : g++ -std=c++11
Build TZlibTransport ...... : yes
Build TNonblockingServer .. : yes
Build TQTcpServer (Qt5) ... : no
C++ compiler version ...... : g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
要点:
--disable-tests --disable-tutorial跳过测试与教程代码,显著缩短编译时间;- 保留 C++ 运行时库与全量代码生成器(编译器本体一次性内置全部语言生成器);
--with-py3仅是声明启用,顶层 make 不会构建 Python 库,需按第五章单独安装。
4.4 make 编译
make -j2
编译内容为 thrift 编译器本体(含全部语言生成器)与 C++ 运行时库,耗时数分钟属正常现象。实测以 make -j2 完成且无 Error 输出。
4.5 安装与验证
make install
ln -sf /opt/thrift/bin/thrift /usr/local/bin/thrift
thrift --version
实测回显:
Thrift version 0.25.0
安装产物:/opt/thrift/bin/thrift;/opt/thrift/lib 下的 libthrift-0.25.0.so、libthriftnb-0.25.0.so、libthriftz-0.25.0.so(及 .a 与 .la 文件);/opt/thrift/include/thrift 下的 C++ 头文件。其中 libthriftnb 为非阻塞服务端库(依赖 libevent),libthriftz 为 zlib 压缩传输库。
五、Python3 运行时安装(可选)
5.1 安装构建依赖
Python3 绑定随源码树发布于 lib/py 目录,构建需要 setuptools 与 pip,Ubuntu 22.04 最小安装两者皆缺,需先补齐:
apt-get install -y python3-setuptools python3-pip
5.2 单独构建安装 Python 库
cd /opt/src/thrift-0.25.0/lib/py
make install
python3 -c 'import thrift; print(thrift.__file__)'
实测回显:
thrift py module: /usr/local/lib/python3.10/dist-packages/thrift/__init__.py
注意:Python 库安装路径由系统 Python 决定(/usr/local/lib/python3.10/dist-packages),不受 configure 的 --prefix 影响,这是 thrift 0.25.0 实测行为。
六、Java 运行时集成(libthrift)
6.1 Maven 依赖引入
在业务工程 pom.xml 中加入以下依赖(版本与编译器一致):
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.25.0</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
</dependency>
三点说明(均为实测结论):
- libthrift 0.25.0 生成的 Java 代码使用
@javax.annotation.Generated注解,JDK 9 之后 JDK 不再内置该包,必须补充 javax.annotation-api 依赖,否则编译报 package javax.annotation does not exist; - libthrift 0.25.0 传递依赖 slf4j-api 1.7.36,日志实现应使用 slf4j-simple 1.7.36 对齐;若引入 2.x 版本,启动时会报 Failed to load class org.slf4j.impl.StaticLoggerBinder 且日志静默;
- 若使用分帧传输,TFramedTransport 位于 org.apache.thrift.transport.layered 包(0.25.0 实测),旧包路径编译报 cannot find symbol。
6.2 中央仓库依赖解析验证
执行 mvn -q package dependency:copy-dependencies -DoutputDirectory=target/lib 后,target/lib 目录实测包含:
libthrift-0.25.0.jar
javax.annotation-api-1.3.2.jar
slf4j-api-1.7.36.jar
slf4j-simple-1.7.36.jar
commons-lang3-3.18.0.jar
httpclient5-5.2.1.jar
httpcore5-5.2.jar
httpcore5-h2-5.2.jar
jakarta.annotation-api-2.1.1.jar
jakarta.servlet-api-5.0.0.jar
七、最小可运行示例验证
以下示例验证「IDL 编译生成 Java 代码 + Maven 构建 + TSimpleServer 启动 + 客户端 RPC 调用」全链路。完整工程创建过程与代码见第 6.1 节依赖之上的工程结构,此处从 IDL 开始。
7.1 编写 IDL 文件
创建 /opt/thrift-demo/src/main/thrift/user_service.thrift:
namespace java com.example.thrift.demo
struct UserProfile {
1: required i64 userId,
2: required string userName,
3: optional string email,
4: optional i32 age,
5: optional list<string> tags
}
exception UserNotFound {
1: string message
}
service UserService {
bool createUser(1: UserProfile profile),
UserProfile getUser(1: i64 userId) throws (1: UserNotFound unfe),
i64 countUsers()
}
7.2 生成 Java 代码
cd /opt/thrift-demo
thrift --gen java src/main/thrift/user_service.thrift
cp -r gen-java/com src/main/java/
生成文件清单:
gen-java/com/example/thrift/demo/UserNotFound.java
gen-java/com/example/thrift/demo/UserProfile.java
gen-java/com/example/thrift/demo/UserService.java
7.3 服务端代码
创建 /opt/thrift-demo/src/main/java/com/example/thrift/demo/ThriftServer.java:
package com.example.thrift.demo;
import org.apache.thrift.TProcessor;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ThriftServer {
private static final Map<Long, UserProfile> USER_STORE = new HashMap<>();
public static class UserServiceHandler implements UserService.Iface {
@Override
public boolean createUser(UserProfile profile) {
USER_STORE.put(profile.getUserId(), profile);
System.out.println("[server] createUser ok, userId=" + profile.getUserId()
+ ", userName=" + profile.getUserName());
return true;
}
@Override
public UserProfile getUser(long userId) throws UserNotFound {
UserProfile profile = USER_STORE.get(userId);
if (profile == null) {
throw new UserNotFound("userId=" + userId + " not found");
}
return profile;
}
@Override
public long countUsers() {
return USER_STORE.size();
}
}
public static void main(String[] args) throws TTransportException {
TProcessor processor = new UserService.Processor<>(new UserServiceHandler());
TServerSocket serverSocket = new TServerSocket(9090);
TServer.Args serverArgs = new TServer.Args(serverSocket);
serverArgs.processor(processor);
serverArgs.protocolFactory(new TBinaryProtocol.Factory());
TServer server = new TSimpleServer(serverArgs);
System.out.println("[server] TSimpleServer listening on port 9090 ...");
server.serve();
}
}
7.4 编译打包
cd /opt/thrift-demo
mvn -q package dependency:copy-dependencies -DoutputDirectory=target/lib
ls target/thrift-demo-1.0.0.jar
实测回显:
target/thrift-demo-1.0.0.jar
7.5 启动服务端并验证 JVM 堆参数
JVM 堆内存限定为 256 至 512 MB:
cd /opt/thrift-demo
java -Xms256m -Xmx512m -cp target/classes:target/lib/* com.example.thrift.demo.ThriftServer
服务端启动回显:
[server] TSimpleServer listening on port 9090 ...
另开一个终端验证堆参数生效(java 进程 PID 以实际为准):
jps -lv
ps -ef | grep ThriftServer
实测回显:
17991 com.example.thrift.demo.ThriftServer -Xms256m -Xmx512m
root 17679 17673 0 09:22 ? 00:00:00 bash -c cd /opt/thrift-demo && java -Xms256m -Xmx512m -cp target/classes:target/lib/* com.example.thrift.demo.ThriftServer
root 17681 17679 0 09:22 ? 00:00:00 java -Xms256m -Xmx512m -cp target/classes:target/lib/* com.example.thrift.demo.ThriftServer
若需修改堆内存,直接调整启动命令中的 -Xms 与 -Xmx 取值后重启进程即可。
7.6 客户端 RPC 调用
创建 /opt/thrift-demo/src/main/java/com/example/thrift/demo/ThriftClient.java:
package com.example.thrift.demo;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import java.util.ArrayList;
import java.util.List;
public class ThriftClient {
public static void main(String[] args) {
TTransport transport = null;
try {
transport = new TSocket("127.0.0.1", 9090, 3000);
transport.open();
TBinaryProtocol protocol = new TBinaryProtocol(transport);
UserService.Client client = new UserService.Client(protocol);
List<String> tags = new ArrayList<>();
tags.add("rpc");
tags.add("java");
UserProfile profile = new UserProfile();
profile.setUserId(1001);
profile.setUserName("zhangsan");
profile.setEmail("zhangsan@example.com");
profile.setAge(28);
profile.setTags(tags);
System.out.println("[client] createUser -> " + client.createUser(profile));
System.out.println("[client] countUsers -> " + client.countUsers());
UserProfile fetched = client.getUser(1001);
System.out.println("[client] getUser(1001) -> userId=" + fetched.getUserId()
+ ", userName=" + fetched.getUserName()
+ ", email=" + fetched.getEmail()
+ ", age=" + fetched.getAge()
+ ", tags=" + fetched.getTags());
} catch (UserNotFound unfe) {
System.err.println("[client] UserNotFound: " + unfe.getMessage());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (transport != null) {
transport.close();
}
}
}
}
执行调用:
java -cp target/classes:target/lib/* com.example.thrift.demo.ThriftClient
实测回显:
[client] createUser -> true
[client] countUsers -> 1
[client] getUser(1001) -> userId=1001, userName=zhangsan, email=zhangsan@example.com, age=28, tags=[rpc, java]
同时服务端日志追加:
[server] createUser ok, userId=1001, userName=zhangsan
RPC 全链路验证通过。
八、注意事项
- 编译器与运行时版本必须一致:编译器 0.25.0 生成代码与 libthrift 0.25.0 配套,混用不同大版本可能出现序列化兼容或 API 不匹配问题。
- configure 的语言裁剪项只影响「随源码树编译哪些语言的运行时库」,不影响 thrift 编译器的代码生成能力,生成器永远全部可用。
- C++ 运行时库安装于 /opt/thrift/lib,该目录默认不在动态链接器搜索路径中,编译链接 C++ 程序时需设置
export LD_LIBRARY_PATH=/opt/thrift/lib:$LD_LIBRARY_PATH。 - Python3 运行时库不随顶层 make 构建,必须进入 lib/py 目录单独 make install,且依赖 setuptools 与 pip,缺失时的报错形态见常见问题。
- 生成的 Java 代码默认包含日期的 @Generated 注解,会影响增量构建确定性,可改用
thrift --gen java:generated_annotations=undated生成无日期注解代码。
九、常见问题
Q1: lib/py 执行 make install 报 ModuleNotFoundError: No module named setuptools?
Ubuntu 22.04 最小安装缺少 setuptools,执行 apt-get install -y python3-setuptools 后重试。
Q2: 补装 setuptools 后 make install 又报 /usr/bin/python3: No module named pip?
Python 库安装钩子需要 pip,执行 apt-get install -y python3-pip 后重试,实测即可安装成功,模块落入 /usr/local/lib/python3.10/dist-packages。
Q3: 生成的 Java 代码参与 Maven 编译时报 package javax.annotation does not exist?
生成的类使用了 @javax.annotation.Generated 注解,该包自 JDK 9 起从 JDK 移除。在 pom.xml 增加 javax.annotation:javax.annotation-api:1.3.2 依赖后重新构建即可,实测有效。
Q4: 服务端启动时输出 SLF4J: Failed to load class org.slf4j.impl.StaticLoggerBinder 且看不到业务日志?
libthrift 0.25.0 传递依赖 slf4j-api 1.7.36,日志实现必须同为 1.7.x。将 slf4j-simple 降到 1.7.36 对齐后告警消失、日志正常输出,实测有效。
Q5: 卸载重装后执行 thrift 提示 command not found?
此前创建过 /usr/local/bin/thrift 软链,源文件被卸载后软链悬空。执行 rm -f /usr/local/bin/thrift 后重新按 4.5 步创建软链即可。
十、卸载方式
10.1 源码方式卸载
保留源码目录时可直接使用 autotools 卸载目标:
cd /opt/src/thrift-0.25.0
make uninstall
实测行为:执行完成后退出码为 0,/opt/thrift/bin、/opt/thrift/lib、/opt/thrift/include 下的文件被删除,但目录骨架会保留(autotools 不删除空目录)。
10.2 手工清理
rm -f /usr/local/bin/thrift
rm -rf /opt/thrift
rm -rf /opt/src
若安装过 Python3 运行时库,还需清理模块目录:
rm -rf /usr/local/lib/python3.10/dist-packages/thrift
rm -f /usr/local/lib/python3.10/dist-packages/thrift-0.25.0-py3.10.egg-info
验证卸载结果:
which thrift
实测回显(无输出且退出码为 1,即 which 未找到命令)即可确认卸载完成。
10.3 Java 运行时移除
在业务工程 pom.xml 中删除 org.apache.thrift:libthrift 及配套依赖,随后执行 mvn clean 清理构建产物即可。