TradingView Webhooks接收丢失问题求助:基于AWS Lightsail的量化交易系统
我们在AWS Lightsail的Ubuntu服务器上运行基于aiohttp的Python Web服务器,作为交易机器人接收TradingView警报Webhooks,并根据请求体数据在Binance交易所执行交易。当前存在部分TradingView警报Webhooks未被接收、丢失的问题,已知TradingView会自动取消耗时超过3秒的请求。
已完成排查
- 检查服务器日志未发现错误
- 迁移至AWS Lightsail以提升稳定性
- 排查网络连接问题,未发现异常
解决方案建议
优先返回请求确认,异步处理交易逻辑
TradingView对超时极度敏感,绝不能在Webhook请求的同步处理流程中直接调用Binance交易接口(这一步可能因网络或交易所响应延迟超出3秒阈值)。正确的做法是:先读取请求体并立即返回200 OK确认接收,再通过异步任务队列或aiohttp后台任务处理交易逻辑。示例代码:from aiohttp import web import asyncio async def handle_webhook(request): # 先读取并保存请求体,避免后续丢失 payload = await request.json() # 异步启动交易处理任务,不阻塞响应 asyncio.create_task(process_binance_trade(payload)) # 立即返回成功响应 return web.Response(status=200) async def process_binance_trade(payload): # 这里处理Binance API调用、交易执行等逻辑 pass细化Webhook接收日志
当前日志粒度不足,无法定位请求是否真的到达服务器。需在aiohttp中添加中间件,记录每个请求的关键信息:请求时间、请求头哈希、请求体哈希、响应状态、响应耗时。示例中间件:@web.middleware async def webhook_log_middleware(request, handler): start_time = asyncio.get_event_loop().time() # 读取并保存请求体 raw_body = await request.read() # 记录请求元数据(避免日志过大,只存哈希值) print(f"Webhook received: timestamp={start_time}, body_hash={hash(raw_body)}, headers={dict(request.headers)}") # 重置请求体,让后续处理能正常读取 request._payload = raw_body # 处理请求并记录响应信息 response = await handler(request) elapsed = asyncio.get_event_loop().time() - start_time print(f"Webhook responded: status={response.status}, elapsed={elapsed:.2f}s") return response通过这些日志可以确认:TradingView是否真的发送了请求、服务器响应耗时是否接近3秒阈值。
监控服务器资源瓶颈
即使迁移到Lightsail,仍需检查服务器CPU、内存、网络带宽是否存在耗尽情况。使用htop实时监控资源占用,或通过AWS CloudView查看Lightsail实例的性能指标——资源瓶颈会导致aiohttp服务器无法及时处理新请求。调整aiohttp服务器超时配置
主动缩短服务器的请求处理超时时间,确保响应能在2秒内完成(留1秒缓冲给网络延迟)。启动服务器时可配置:if __name__ == "__main__": app = web.Application(middlewares=[webhook_log_middleware]) app.add_routes([web.post('/webhook', handle_webhook)]) # 设置总超时为2秒 runner = web.AppRunner(app, timeout=web.Timeout(total=2)) await runner.setup() site = web.TCPSite(runner, '0.0.0.0', 8080) await site.start() await asyncio.Event().wait()开启TradingView警报重试
在TradingView的警报设置中,启用请求重试功能(若支持),设置较短的重试间隔,覆盖临时网络波动或服务器忙导致的请求丢失情况。
内容的提问来源于stack exchange,提问作者Morteza Osanloo

