c# - Azure Function 响应中的流式处理输出
问题描述
我有一个有效的 HTTP 触发器函数,它启动一个new Process
. 我想做的是获取标准错误/输出并将它们发送到 Web 客户端,但我还没有弄清楚流程处理和流式传输的正确组合以使其工作......
通常,一切都运行,但似乎没有输出发送到客户端。如果可能的话,我想刷新每一行,尽管我知道网络服务器可能会阻止它。目前我正在通过 AF webjob 主机在本地进行测试。我猜这与对象的生命周期有关,或者这可能是不可能的。
我尝试了各种方法,但这是我目前拥有的代码,它运行并且过程成功完成,输出被记录,但没有输出到 Postman(甚至不是 200 OK):
[FunctionName("Function1")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req,
CancellationToken cancellationToken,
TraceWriter log
)
{
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream, Encoding.UTF8, 1, true))
//using (var streamWriter = new StreamWriter(memoryStream))
{
streamWriter.WriteLine($"Starting execution.");
using (var proc = new Process())
{
proc.StartInfo.FileName = @"D:\Runner.exe";
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
//proc.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
//{
// log.Info(e.Data);
// streamWriter.WriteLine(e.Data);
//};
//proc.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
//{
// log.Error(e.Data);
// streamWriter.WriteLine(e.Data);
//};
proc.Start();
/// Need to drain the output otherwise the process will
/// hang and not stop until the computer is shut down.
/// It can be killed by Administrator but will remain as
/// a process until restarted.
/// taskkill /f /im runner.exe
/// tasklist /fi "imagename eq runner.exe"
while (!proc.StandardOutput.EndOfStream)
{
log.Info(proc.StandardOutput.ReadLine());
streamWriter.Flush();
}
//proc.WaitForExit();
streamWriter.Flush();
var response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(memoryStream)
};
return response;
}
}
}
解决方案
我的例子比问题要新一些,但这是你如何做到的。
我没有runner.exe
,我认为使用 CliWrap 是使用System.Diagnostics.Process
. 我尝试使用不需要同步 IO 的解决方案,但如果您确实需要做一些确实需要的事情,您可以"FUNCTIONS_V2_COMPATIBILITY_MODE": true
在函数主机环境变量中设置以使其工作。
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using CliWrap;
namespace AdamCoulter
{
public static class StreamBack
{
[FunctionName("StreamBack")]
public static HttpResponseMessage Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestMessage request)
{
var response = new HttpResponseMessage
{
RequestMessage = request,
Content = new PushStreamContent(new Func<Stream, HttpContent, TransportContext, Task>(RunTerraform), "text/event-stream")
};
response.Headers.TransferEncodingChunked = true;
return response;
}
public static async Task RunTerraform(Stream stream, HttpContent content, TransportContext context)
{
_ = await Cli.Wrap("terraform")
.WithArguments("init")
.WithWorkingDirectory("/Volumes/Code/tftest/")
.WithStandardOutputPipe(PipeTarget.ToStream(stream))
.ExecuteAsync();
stream.Close();
}
}
}
GET /api/StreamBack HTTP/1.1
Host: localhost:7071
chrome 中的增量流式输出(在生成终端输出时逐位显示):
[0m[1mInitializing the backend...[0m
[0m[1mInitializing provider plugins...[0m
- Reusing previous version of hashicorp/azurerm from the dependency lock file
- Using previously-installed hashicorp/azurerm v2.58.0
[0m[1m[32mTerraform has been successfully initialized![0m[32m[0m
[0m[32m
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.[0m
推荐阅读
- python - Tensorflow 警告 - 无法加载动态库“cupti64_101.dll”;dlerror: cupti64_101.dll 未找到
- file - 当前的屏幕分辨率是否保存在任何地方的文件中?(窗口 7)
- angular9 - 如何从 Angular7 中可用的 Angular9 中的 ComponentFactoryResolver 访问 _factories 属性?
- c++ - 在 C++ 中创建字符串时抛出奇怪的错误
- ios - 如何在没有 3rd 方库 iOS Swift 的情况下绘制饼图,获得的标记填充总标记中的一些颜色
- reactjs - 带有事件的 Swiperjs 反应
- php - Laravel 的内置 Auth 功能在使用带有前缀 url 的本地化时会导致错误
- python - 安装 anaconda 后,无法导入新的 pip 安装模块
- python - Python将不相等的数据帧与真/假文本进行比较以获取列输出
- python - 如何处理字符串列表,其中每个字符串也可能是逗号分隔的字符串列表?