1.上传pb
2、创建上游服务
3、创建路由
4、第3步插件选择grpc-transcode
路由配置
rpc 服务端口是8080,传递参数请求是正常的
现在问题是通过apisix 服务+端口直接请求rpc服务,rpc服务此时总是拿不到请求参数 172.29.119.29:9080/mydemo/ping
没得到解决
没人回答自己来记录下
需要开启apisix 内置插件 将header转换为metadata
{
"proxy-rewrite": {
"headers": {
"stripe-signature": "$http_stripe_signature",
"account-id": "$http_x_account_id"
}
}
}
场景 1:暴露 Stripe Webhook 接口
需求:将 gRPC 方法 HandleWebhook 通过 HTTP 暴露,需要:
- 从 HTTP Header 中提取
Stripe-Signature - 从 URL 路径中提取
account_id(如:/api/v2/payment/webhook/stripe/acct_1SLePIFRiaUgXx9u) - 将原始请求体作为
payload传递 - 响应要求:Stripe 要求返回纯文本
"ok",否则会认为接收失败并重试
方案 A:使用 APISIX grpc-transcode(当前方案)
步骤 1:Proto 文件处理
# 1. 需要将 proto 文件转换为 .pb 格式(包含所有依赖)
protoc --proto_path=. \
--include_imports \
--descriptor_set_out=payment_stripe_webhook.pb \
payment_stripe/v1/hh_payment_stripe.proto
# 2. 将 .pb 文件转换为 base64 编码
base64 -i payment_stripe_webhook.pb > payment_stripe_webhook_base64.txt
# 3. 通过 APISIX Admin API 上传 base64 内容
curl -X PUT http://apisix:9180/apisix/admin/proto/2 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-d @payment_stripe_webhook_base64.txt
问题:
- 需要手动处理依赖关系(
import语句) - 每次 proto 文件变更都需要重新生成和上传
- base64 编码后的内容难以阅读和调试
- 上传失败时错误信息不明确
步骤 2:编写复杂的 Lua 脚本
由于需要从 Header 和 URL 路径中提取参数,必须使用 serverless-pre-function 插件编写 Lua 脚本:
return function(conf, ctx)
-- 1. 从 header 获取 Stripe-Signature
local headers = ngx.req.get_headers()
local stripe_signature = headers['Stripe-Signature'] or headers['stripe-signature'] or ''
-- 2. 从 URI 路径中提取 account_id
local uri = ngx.var.uri
local account_id = ''
local match = string.match(uri, '/api/v2/payment/webhook/stripe/([^/]+)')
if match then
account_id = match
end
-- 3. 读取请求体(payload)
ngx.req.read_body()
local body = ngx.req.get_body_data()
local payload_raw = ''
if body then
payload_raw = body
end
-- 4. 构建符合 proto 定义的 JSON 请求体
local cjson = require('cjson')
local request_data = {}
-- 处理 payload(proto 定义是 bytes 类型)
if payload_raw ~= '' then
request_data.payload = payload_raw
else
request_data.payload = ''
end
-- 5. 添加 signature 和 account_id
if stripe_signature ~= '' then
request_data.signature = stripe_signature
end
if account_id ~= '' then
request_data.account_id = account_id
end
-- 6. 重新设置请求体
ngx.req.set_body_data(cjson.encode(request_data))
return
end
问题:
- 需要熟悉 Lua 和 OpenResty 的 API
- 脚本逻辑复杂,容易出错
- 调试困难,错误信息不直观
- 维护成本高,每次需求变更都需要修改脚本
步骤 3:配置 APISIX 路由(包含响应格式转换)
由于 gRPC 返回的是 BaseModel 格式:
{
"base_model": {
"base_code": 0,
"base_msg": "success"
}
}
但 Stripe Webhook 要求响应必须是纯文本 "ok",否则会认为接收失败并重试。因此需要额外配置 response-rewrite 插件:
{
"uri": "/api/v2/payment/webhook/stripe/*",
"host": "ark-payment-api-test.hahavending.com",
"methods": ["POST"],
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": ["return function(conf, ctx)\n -- 上面 50+ 行的 Lua 代码\nend"]
},
"grpc-transcode": {
"service": "hh_payment_stripe.v1.PaymentStripe",
"method": "HandleWebhook",
"proto_id": "2",
"pb_option": ["int64_as_string"],
"deadline": 5000
},
"response-rewrite": {
"status_code": 200,
"body": "ok",
"headers": {
"Content-Type": "text/plain"
}
}
},
"upstream": {
"scheme": "grpc",
"type": "roundrobin",
"nodes": {
"hh-payment-stripe-svc.ark-project-test.svc.cluster.local:8080": 1
}
}
}
问题:
- 需要额外配置
response-rewrite插件 - 不同 webhook 的响应格式要求不同,需要为每个 webhook 单独配置
- 响应转换逻辑分散在配置中,难以维护
步骤 4:调试和排错
实际遇到的问题:
-
Proto 编译错误 proto load error: unknown keyword 'CuIFChxnb29nbGUvcHJvdG9idWYvc3RydWN0LnByb3Rv'
- 原因:base64 编码格式问题
- 解决:需要反复尝试不同的编码方式
-
服务方法未找到 compiled proto service not found Undefined service method: mydemo.Mydemo/Ping
- 原因:APISIX 缓存问题或 proto 编译失败
- 解决:需要重启 APISIX 或清除缓存
-
上游连接错误 upstream sent no valid HTTP/1.0 header while reading response header from upstream Connection reset by peer
- 原因:gRPC 服务地址配置错误或网络问题
- 解决:需要检查 Kubernetes Service 配置和网络连通性
总耗时:约 4-6 小时(包括调试和排错)