2017-04-05 54 views
0

以下是运行.NET Framework的ASP.NET Core API。这是我的MVC控制器之一。将缓冲区写入响应流或长时间运行请求结束?

我必须从外部服务获取数据,只让我一次获得相当小的数据缓冲区 - 我无法控制这一点。比方说,我得到500行每缓冲区中的数据,但我的客户希望一下子就被格式化为CSV数据的,所以我要循环,并呼吁外部源,像这样:

[HttpGet] 
public async Task<IActionResult> Get(MyRequest request) 
{ 
    var aggregateResponse = await client.GetDataAsync(request); 
    while (aggregateResponse.HasMoreData) 
    { 
     request.Cookie = aggregateResponse.Cookie; 
     var response = await client.GetDataAsync(request); 
     //Data is a list of objects containing n number of properties 
     aggregateResponse.Data.Concat(response.Data) 

     //I need the cookie from the previous response to get the next buffer 
     aggregateResponse.Cookie = response.Cookie; 
     aggregateResponse.HasMoreData = response.HasMoreData; 
    } 
    //runs through a generic IEnumerable CSV output formatter (uses reflection) 
    return Ok(aggregateResponse.Data); 
} 

可悲的是这可以花100-200个循环找回所有数据(aggregateResponse.Data中的50,000 - 100,000个列表项),但我没有太多的选择。

  • 难道是更有效的数据的每一个缓冲区格式化为CSV在循环,并将其写入到响应每次流,或者最好等到最终像我现在在做什么?例如:

    [HttpGet] 
    public async Task<IActionResult> Get(MyRequest request) 
    
    { 
        var response = await client.GetDataAsync(request); 
        await Response.WriteAsync(formatBeginningData(response.Data)) 
        while (request.HasMoreData) 
        { 
         request.Cookie = aggregateResponse.Cookie; 
         response = await client.GetDataAsync(request); 
         await Response.WriteAsync(formatData(response.Data)) 
         request.Cookie = response.Cookie; 
         request.HasMoreData = response.HasMoreData; 
        } 
    
        return Ok(); 
    } 
    
  • 我连续使用异步在这种方法进行数据呼叫,但是这意味着线程将被切换了很多次的挫折感。这样做是否异步实际上给我一个性能下降?是否应该全部是同步的(方法签名和数据调用)?

回答

1

难道是更有效的数据的每一个缓冲区格式化为CSV在循环,并将其写入到响应每次流,或者最好等到最终像我现在在做什么?

您可以,但除非数据是太大,不适合到内存中,我不会推荐它。

流媒体的优势在于数据不必适应内存,客户端可以逐渐接收数据。

流式传输的缺点是必须在流开始之前发送HTTP响应代码,因此在流式传输开始后无法通知客户端错误。因此,如果其中一个GetDataAsync调用失败,客户端仍然会获得200 OK,但是其数据意外中断。

我在这种方法中不断地使用async进行数据调用,但这意味着线程将会转换很多次。这样做是否异步实际上给我一个性能下降?是否应该全部是同步的(方法签名和数据调用)?

否; ASP.NET Core上的异步代码具有与同步代码相同或更少的线程切换。