Веб-API ASP.NET: сбрасывание PushStreamContent не выполняется
Я использую PushStreamContent
в ASP.NET Web API для передачи событий с сервера на клиент (используя события, отправленные сервером). После каждого отправленного события я звоню Flush
на Stream
передать буферизованные данные клиенту. Однако я заметил, что промывка (не всегда) происходит. Иногда часть данных отправляется клиенту, а остальная часть отправляется при записи следующего события (что может произойти через несколько секунд).
Вот пример кода:
public class MyController : ApiController
{
private static readonly string[] LineSeparators
= new[] { Environment.NewLine };
public HttpResponseMessage GetData(string id)
{
var response = Request.CreateResponse();
response.Content = new PushStreamContent(
new Func<Stream, HttpContent, TransportContext, Task>(StartStream),
new MediaTypeHeaderValue("text/event-stream") { CharSet = "UTF-8" });
return response;
}
private async Task StartStream(Stream outputStream, HttpContent content, TransportContext context)
{
using (outputStream)
using (var writer = new StreamWriter(outputStream, new UTF8Encoding(false)))
{
writer.NewLine = "\n";
while (true)
{
WriteEvent(writer, "ping", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
private static void WriteEvent(TextWriter writer, string eventType, string data)
{
writer.WriteLine("event:" + eventType);
writer.WriteLine("data:" + data);
writer.WriteLine();
writer.Flush(); // StreamWriter.Flush calls Flush on underlying Stream
}
}
Как я могу отключить буферизацию данных или принудительно сбросить данные?
2 ответа
Я получил это работает.
В моем случае буферизация была проблемой. Мне пришлось
1) отключить gzip для моих ответов <urlCompression doStaticCompression="true" doDynamicCompression="false" />
2) Убедитесь, что прокси на Prod (Nginx) тоже не буферизуется
Потратив целый день на то, чтобы выяснить, в чем проблема, и зайти так далеко (отчаянно), чтобы получить награду, я обнаружил, что проблема заключается в том, что я использовал HttpSelfHostServer
и нужно было настроить TransferMode = TransferMode.Streamed
на HttpSelfHostConfiguration
, Это все.
Источником проблемы является сбрасываемый поток.
В своем примере кода вы деформируете исходный поток с помощью StreamWriter, а затем очищаете StreamWriter .
Вам также необходимо очистить исходный поток:
private async Task StartStream(Stream outputStream, HttpContent content, TransportContext context)
{
using (outputStream)
using (var writer = new StreamWriter(outputStream, new UTF8Encoding(false)))
{
writer.NewLine = "\n";
while (true)
{
WriteEvent(writer, "ping", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
outputStream.Flush();
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}