通过 Python + gRPC 提供 FFT (快速傅里叶变换) 远程调用服务,支持跨语言调用。
本项目提供一个基于 gRPC 的 FFT 计算微服务:
- 输入: 采样频率、采样点数、时域数据
- 输出: 频率数组、幅度数组、相位数组
- 用途: 让其他语言(如 Go、Java、C++ 等)可以远程调用 Python 的 NumPy FFT 计算能力
| 测试场景 | 采样点数 | RPC 调用耗时 |
|---|---|---|
| 10Hz 正弦波 | 100 | 2.94ms |
| 混合频率信号 | 200 | 370µs |
- ✅ gRPC 服务提供 FFT 计算 (时域 → 频域)
- ✅ 返回频率、幅度、相位数组
- ✅ PyInstaller 打包为可执行文件
- ✅ Docker 构建 ARM64 Debian 可执行文件
- ✅ Go 语言客户端示例
py-calc-rpc/
├── proto/ # Protocol Buffers 定义
│ └── calc.proto
├── generated/ # 生成的 Python gRPC 代码
│ ├── calc_pb2.py
│ └── calc_pb2_grpc.py
├── go-client/ # Go 客户端示例
│ ├── main.go
│ ├── go.mod
│ ├── generate_proto.sh
│ └── gen/calc/ # 生成的 Go gRPC 代码
├── server.py # gRPC 服务器
├── generate_proto.py # Python 代码生成脚本
├── requirements.txt # Python 依赖
├── app.spec # PyInstaller 配置
├── Dockerfile.build # Docker 构建文件
├── build_arm64.sh # ARM64 构建脚本
└── README.md # 本文档
pip install -r requirements.txtpython generate_proto.pypython server.py --port 50051cd go-client
chmod +x generate_proto.sh
./generate_proto.sh
go run main.go输出示例:
连接到服务器: localhost:50051
=== 示例1: 10Hz 正弦波 FFT ===
⏱️ RPC 调用耗时: 2.943459ms
采样频率: 100.0 Hz
采样点数: 100
信号频率: 10.0 Hz
最大幅度频率: 10.00 Hz (幅度: 50.00)
=== 示例2: 混合频率信号 (5Hz + 20Hz) FFT ===
⏱️ RPC 调用耗时: 370.625µs
检测到的主要频率峰值:
频率: 5.00 Hz, 幅度: 100.00
频率: 20.00 Hz, 幅度: 50.00
=== 总耗时: 3.378958ms ===
chmod +x build_arm64.sh
./build_arm64.sh输出文件: dist/calc-server (约 36MB)
# 拷贝到容器
docker cp dist/calc-server debian-container-host:/root/
# 在容器中启动服务
docker exec -d debian-container-host sh -c '/root/calc-server --port 50051 > /tmp/calc.log 2>&1'
# 查看日志
docker exec debian-container-host cat /tmp/calc.log
# 检查服务状态
docker exec debian-container-host ss -tlnp | grep 50051# 上传
scp dist/calc-server user@remote-host:/opt/
# 远程启动
ssh user@remote-host "chmod +x /opt/calc-server && nohup /opt/calc-server --port 50051 &"service CalcService {
rpc FFT(FFTRequest) returns (FFTResponse);
}
message FFTRequest {
double sampling_rate = 1; // 采样频率 (Hz)
int32 num_samples = 2; // 采样点数
repeated double time_data = 3; // 时域数据
}
message FFTResponse {
repeated double frequencies = 1; // 频率数组
repeated double amplitudes = 2; // 幅度数组
repeated double phases = 3; // 相位数组
}import grpc
from generated import calc_pb2, calc_pb2_grpc
channel = grpc.insecure_channel('localhost:50051')
stub = calc_pb2_grpc.CalcServiceStub(channel)
request = calc_pb2.FFTRequest(
sampling_rate=100.0,
num_samples=100,
time_data=[...] # 时域数据
)
response = stub.FFT(request)
print(response.frequencies)
print(response.amplitudes)import pb "github.com/yourorg/py-calc-rpc/gen/calc"
conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
client := pb.NewCalcServiceClient(conn)
req := &pb.FFTRequest{
SamplingRate: 100.0,
NumSamples: 100,
TimeData: timeData,
}
resp, _ := client.FFT(context.Background(), req)| 操作 | 命令 |
|---|---|
| 安装依赖 | pip install -r requirements.txt |
| 生成 Python gRPC 代码 | python generate_proto.py |
| 启动服务器 | python server.py --port 50051 |
| 构建 ARM64 可执行文件 | ./build_arm64.sh |
| 拷贝到 Docker 容器 | docker cp dist/calc-server container:/root/ |
| 容器内启动服务 | docker exec -d container /root/calc-server |
| 生成 Go gRPC 代码 | cd go-client && ./generate_proto.sh |
| 运行 Go 客户端 | cd go-client && go run main.go |
Python:
- grpcio, grpcio-tools, protobuf
- numpy
- pyinstaller
Go:
- google.golang.org/grpc
- google.golang.org/protobuf
MIT License