如何在ASP.NET Core中用await保持Azure Relay连接超60秒存活?
解决方案
要解决Azure Relay 60秒无数据传输的超时问题,你可以通过**分块传输编码(Chunked Transfer Encoding)**定期发送空的响应块来保持连接活跃,同时异步等待长运行的WCF任务完成。以下是具体实现:
1. 修改控制器方法,实现循环等待+保活逻辑
将原来的GetHeartbeatStr方法改为直接操作HttpContext.Response,启用分块传输,并在等待期间定期发送保活数据:
[HttpGet] [Route("GetHeartbeatStr")] [Produces(MediaTypeNames.Application.Json)] public async Task GetHeartbeatStr() { var request = new MyRequest(); var wcfTask = _client.getHeartbeatStrAsync(request); var keepAliveInterval = TimeSpan.FromSeconds(55); // 比60秒超时短5秒,预留缓冲 // 启用分块传输,让响应可以分段发送 HttpContext.Response.Headers.TransferEncodingChunked = "true"; var responseStream = HttpContext.Response.Body; try { while (!wcfTask.IsCompleted) { // 等待指定时间,或直到WCF任务完成 await Task.WhenAny(wcfTask, Task.Delay(keepAliveInterval)); if (!wcfTask.IsCompleted) { // 发送空的分块作为保活信号 await responseStream.WriteAsync(Array.Empty<byte>(), 0, 0); await responseStream.FlushAsync(); } } // WCF任务完成,返回最终结果 var response = await wcfTask; await HttpContext.Response.WriteAsJsonAsync(response.response); } finally { await responseStream.FlushAsync(); } }
2. 关键逻辑说明
- 分块传输启用:通过设置
TransferEncodingChunked为true,允许响应分多次发送,无需提前知道响应总长度。 - 循环等待+保活:每次等待55秒(小于60秒超时阈值),如果WCF任务未完成,就向响应流写入空字节并刷新,Azure Relay会将这个空块视为有效数据传输,从而重置超时计时器。
- 异步安全:全程使用
await确保异步操作不阻塞线程,符合ASP.NET Core的异步模型。
3. 额外注意事项
- 确保WCF客户端的超时设置大于你的任务实际运行时间,避免WCF端先断开连接。
- 如果保活间隔需要调整,可以根据实际情况修改
keepAliveInterval,但必须小于Azure Relay的60秒超时限制。 - 异常处理:可以在
try块中添加catch逻辑,处理WCF调用或响应流操作中的异常,确保连接正常关闭。
内容的提问来源于stack exchange,提问作者William YK
相关产品推荐
相关产品推荐

