Я запускаю службу как веб-приложение Azure. Проблема в том, что поток ответов не принимается в том виде, в котором он отправляется приложением, а поступает большими порциями. Я предполагаю, что это связано с буферизацией ответов. Мой веб-API ASP.NET Core 6 размещен в IIS в ОС Windows в веб-приложении Azure.
Все работает локально (с использованием локального хостинга IIS), но не в размещенной среде.
Я пробовал следующее:
var responseBodyFeature = context.Features.Get<IHttpResponseBodyFeature>();
if (responseBodyFeature != null)
responseBodyFeature.DisableBuffering();
Установите заголовки ответов, добавив web.config в мой веб-API ASP.NET Core 6:
<httpProtocol>
<customHeaders>
<!-- Disable response buffering -->
<add name = "Buffer" value = "False" />
<add name = "X-Accel-Buffering" value = "no" />
<add name = "Cache-Control" value = "no-cache" />
</customHeaders>
</httpProtocol>
Я проверил, что между ними нет APIM или прокси-сервера, которые могут вызвать буферизацию ответа.
У меня есть следующий код в моем веб-API ASP.NET Core 6:
await foreach (var streamingResponse in response.Response.WithCancellation(canToken))
{
foreach (var choice in streamingResponse.Choices)
{
yield return await Task.Run(() => choice.Text);
await Response.Body.FlushAsync();
}
}
Это также рассматривается ниже, но я не хочу, чтобы это затрагивало другие конечные точки, не связанные с потоковой передачей:
.UseKestrel(options =>
{
options.Limits.MaxResponseBufferSize = 2000
});
Ниже приведен код на стороне клиента, вызывающий веб-API ASP.NET Core 6:
let config = {
'method': "POST",
'cached': false,
headers: {
'Content-Type': 'application/json',
'Authorization': '<token>'
},
body: JSON.stringify(requestBody)
};
const response = await fetch(url, config);
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
while (true) {
const { value, done } = await reader.read();
if (done) break;
console.info(value);
}
Вы должны добиться успеха, если установите для заголовка ответа Transfer-Encoding значение identity
.
Вы можете сделать это в своем web.config или в коде.
@s_v Если вы хотите преодолеть это, просто установите в коде значение «идентичность».
Потоковая передача работала с моим кодом, проблема была в специальном промежуточном программном обеспечении для ведения журнала, которое ожидало полного ответа, прежде чем вернуться к пользователю. Я отключил это промежуточное программное обеспечение, и оно начало работать.
Проблема для меня заключалась в том, что промежуточное программное обеспечение для регистрации ждало регистрации всего результата. Итак, мой код для потоковой передачи был правильным, и простое удаление этого промежуточного программного обеспечения заставило его работать. Поэтому сначала вам следует проверить наличие таких блокирующих промежуточных программ!
Мой код для потоковой передачи в контроллере –
await foreach (var streamingCompletions in azResponse.WithCancellation(cancellationToken))
{
var data = streamingCompletions.Choices.Select(x => x.Text);
string myFinalString = string.Join("", data);
var sseMessage = $"{System.Text.Json.JsonSerializer.Serialize(myFinalString)}";
await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(sseMessage));
await Response.Body.FlushAsync();
}
return new EmptyResult();
Он установлен на «куски»