场景: 捕获本地 gRPC 服务的流量并在控制台显示
# 捕获 localhost:8080 的 gRPC 流量
sudo ./grpcr --input-raw="127.0.0.1:8080" --output-stdout
# 同时记录请求和响应
sudo ./grpcr --input-raw="127.0.0.1:8080" --output-stdout --record-response输出示例:
2 f8762dc4-20fa-11f0-a55f-5626e1cdcfe2 1745492273089274000 1
/SearchService/CurrentTime
{"headers":{":authority":"127.0.0.1:8080",":method":"POST",":path":"/SearchService/CurrentTime",":scheme":"http","content-type":"application/grpc"},"body":"{\"requestId\":\"2\"}"}
{"headers":{":status":"200","content-type":"application/grpc","grpc-status":"0"},"body":"{\"currentTime\":\"2025-04-24T18:57:49+08:00\"}"}
场景: 将生产环境的流量复制到测试环境
# 捕获生产环境流量并转发到测试环境
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-grpc="grpc://test-server:8080" \
--output-stdout场景: 将流量保存到文件以便后续分析
# 录制到文件,每个文件最大 100MB
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-file-directory="/tmp/grpc-capture" \
--output-file-max-size=100 \
--record-response场景: 从录制的文件重放流量
# 以原始速度重放
./grpcr \
--input-file-directory="/tmp/grpc-capture" \
--output-grpc="grpc://target-server:8080" \
--output-stdout
# 以 10 倍速重放
./grpcr \
--input-file-directory="/tmp/grpc-capture" \
--output-grpc="grpc://target-server:8080" \
--input-file-replay-speed=10按方法名过滤:
# 只捕获方法名以 "Get" 开头的请求
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-stdout \
--include-filter-method-match="^.*Get.*$"
# 只捕获特定服务的请求
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-stdout \
--include-filter-method-match="^/UserService/.*$"场景: 控制重放速率避免目标服务过载
# 限制每秒最多处理 100 个请求
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-grpc="grpc://target-server:8080" \
--rate-limit-qps=100场景: 同时输出到多个目标
# 同时输出到控制台、文件和另一个 gRPC 服务
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-stdout \
--output-file-directory="/tmp/backup" \
--output-grpc="grpc://mirror-server:8080" \
--record-response场景: 当目标服务没有启用反射时
# 指定单个 proto 文件
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-stdout \
--proto="./protos/service.proto"
# 指定 proto 文件目录
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-stdout \
--proto="./protos/"生产者模式 (将捕获的流量发送到 MQ):
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-rocketmq-name-server="192.168.1.100:9876" \
--output-rocketmq-topic="grpc-traffic" \
--output-rocketmq-access-key="your-access-key" \
--output-rocketmq-secret-key="your-secret-key"消费者模式 (从 MQ 读取流量并重放):
./grpcr \
--input-rocketmq-name-server="192.168.1.100:9876" \
--input-rocketmq-topic="grpc-traffic" \
--input-rocketmq-group-name="replay-group" \
--input-rocketmq-access-key="your-access-key" \
--input-rocketmq-secret-key="your-secret-key" \
--output-grpc="grpc://target-server:8080"创建 systemd 服务文件 (/etc/systemd/system/grpcreplay.service):
[Unit]
Description=gRPC Replay Service
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/grpcreplay
ExecStart=/opt/grpcreplay/grpcr \
--input-raw="0.0.0.0:8080" \
--output-file-directory="/var/log/grpcreplay" \
--output-file-max-size=500 \
--output-file-max-backups=10 \
--output-file-max-age=7 \
--record-response
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target启动服务:
sudo systemctl daemon-reload
sudo systemctl enable grpcreplay
sudo systemctl start grpcreplay
sudo systemctl status grpcreplayDockerfile:
FROM golang:1.23-alpine AS builder
# 安装依赖
RUN apk add --no-cache libpcap-dev gcc musl-dev
WORKDIR /app
COPY . .
RUN go mod download
RUN CGO_ENABLED=1 go build -o grpcr
FROM alpine:latest
RUN apk add --no-cache libpcap
COPY --from=builder /app/grpcr /usr/local/bin/
ENTRYPOINT ["grpcr"]运行容器:
# 构建镜像
docker build -t grpcreplay .
# 运行 (需要特权模式进行网络捕获)
docker run --privileged --net=host \
-v /tmp/grpc-logs:/logs \
grpcreplay \
--input-raw="0.0.0.0:8080" \
--output-file-directory="/logs" \
--record-responsedeployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpcreplay
spec:
replicas: 1
selector:
matchLabels:
app: grpcreplay
template:
metadata:
labels:
app: grpcreplay
spec:
hostNetwork: true
containers:
- name: grpcreplay
image: grpcreplay:latest
securityContext:
privileged: true
args:
- "--input-raw=0.0.0.0:8080"
- "--output-file-directory=/logs"
- "--record-response"
volumeMounts:
- name: logs
mountPath: /logs
volumes:
- name: logs
hostPath:
path: /var/log/grpcreplay# 增加工作者数量提高并发处理能力
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-grpc="grpc://target:8080" \
--output-grpc-worker-number=10# 调整文件轮转参数
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-file-directory="/fast-ssd/grpc-logs" \
--output-file-max-size=1000 \
--output-file-max-backups=5 \
--output-file-max-age=1# 设置合适的读取深度
./grpcr \
--input-file-directory="/tmp/grpc-capture" \
--input-file-read-depth=50 \
--output-grpc="grpc://target:8080"增加文件描述符限制:
# 临时设置
ulimit -n 65536
# 永久设置 (/etc/security/limits.conf)
* soft nofile 65536
* hard nofile 65536网络缓冲区调优:
# 增加网络缓冲区大小
echo 'net.core.rmem_max = 134217728' >> /etc/sysctl.conf
echo 'net.core.wmem_max = 134217728' >> /etc/sysctl.conf
sysctl -p权限问题:
# 检查是否有 root 权限
sudo -v
# 检查 libpcap 是否正确安装
ldd ./grpcr | grep pcap网络接口问题:
# 列出所有网络接口
ip addr show
# 检查端口是否被占用
netstat -tlnp | grep :8080gRPC 反射问题:
# 测试 gRPC 反射是否可用
grpcurl -plaintext localhost:8080 list
# 使用本地 proto 文件替代反射
sudo ./grpcr \
--input-raw="127.0.0.1:8080" \
--output-stdout \
--proto="./protos/"启用详细日志:
# 设置日志级别为 debug
export SIMPLE_LOG_LEVEL=debug
sudo ./grpcr --input-raw="127.0.0.1:8080" --output-stdout性能监控:
# 使用 pprof 进行性能分析
go tool pprof http://localhost:6060/debug/pprof/profile
# 监控资源使用
top -p $(pgrep grpcr)查看系统日志:
# 查看 systemd 日志
journalctl -u grpcreplay -f
# 查看应用日志
tail -f /var/log/grpcreplay/*.log最小权限原则:
# 创建专用用户 (仍需 root 权限进行网络捕获)
sudo useradd -r -s /bin/false grpcreplay
sudo usermod -aG sudo grpcreplay数据脱敏:
# 使用过滤器排除敏感接口
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-stdout \
--include-filter-method-match="^(?!.*/(Login|Password|Secret)).*$"健康检查脚本:
#!/bin/bash
# health-check.sh
PROCESS_COUNT=$(pgrep -c grpcr)
if [ $PROCESS_COUNT -eq 0 ]; then
echo "grpcreplay is not running!"
# 发送告警
curl -X POST "https://hooks.slack.com/..." \
-d '{"text":"grpcreplay service is down!"}'
exit 1
fi
echo "grpcreplay is running normally"日志轮转配置 (/etc/logrotate.d/grpcreplay):
/var/log/grpcreplay/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 root root
postrotate
systemctl reload grpcreplay
endscript
}
存储容量估算:
每个请求大小 ≈ 1-10KB (取决于 payload 大小)
QPS = 1000
每日数据量 ≈ 1000 * 5KB * 86400 ≈ 432GB/天
网络带宽估算:
原始流量: 100Mbps
镜像流量: 100Mbps (1:1 复制)
总带宽需求: 200Mbps
渐进式部署:
# 第一阶段:只记录,不转发
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-file-directory="/tmp/test" \
--rate-limit-qps=10
# 第二阶段:小流量转发
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-grpc="grpc://test-server:8080" \
--rate-limit-qps=100
# 第三阶段:全流量转发
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-grpc="grpc://test-server:8080"A/B 测试:
# 将 50% 流量发送到新版本服务
# (需要在应用层实现流量分割逻辑)
sudo ./grpcr \
--input-raw="0.0.0.0:8080" \
--output-grpc="grpc://service-v1:8080" \
--output-grpc="grpc://service-v2:8080" \
--include-filter-method-match=".*" \
--rate-limit-qps=500自动化部署脚本:
#!/bin/bash
# deploy.sh
set -e
# 下载最新版本
wget https://github.com/vearne/grpcreplay/releases/latest/download/grpcr-linux-amd64.tar.gz
tar -xzf grpcr-linux-amd64.tar.gz
# 停止旧服务
sudo systemctl stop grpcreplay
# 备份旧版本
sudo cp /opt/grpcreplay/grpcr /opt/grpcreplay/grpcr.backup
# 安装新版本
sudo cp grpcr /opt/grpcreplay/
sudo chmod +x /opt/grpcreplay/grpcr
# 启动服务
sudo systemctl start grpcreplay
# 验证服务状态
sleep 5
sudo systemctl is-active grpcreplay || {
echo "Service failed to start, rolling back..."
sudo cp /opt/grpcreplay/grpcr.backup /opt/grpcreplay/grpcr
sudo systemctl start grpcreplay
exit 1
}
echo "Deployment successful!"监控脚本:
#!/bin/bash
# monitor.sh
while true; do
# 检查进程状态
if ! pgrep -f grpcr > /dev/null; then
echo "$(date): grpcreplay process not found, restarting..."
sudo systemctl restart grpcreplay
fi
# 检查磁盘空间
DISK_USAGE=$(df /var/log/grpcreplay | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
echo "$(date): Disk usage is ${DISK_USAGE}%, cleaning old files..."
find /var/log/grpcreplay -name "*.log.gz" -mtime +7 -delete
fi
sleep 60
done这些示例和最佳实践涵盖了从基础使用到生产环境部署的各个方面,帮助你更好地使用 grpcreplay 工具。根据具体需求选择合适的配置和部署方式。