Azure Functions新增Event Hub输出绑定后应用关闭无法写入数据
Azure Event Hub 转存函数启动异常、写入失败排查
问题场景
开发Azure应用函数实现从源Event Hub读取数据,处理后写入目标Event Hub。初始仅实现读取+日志打印逻辑时函数可正常运行,新增Event Hub输出绑定后发布到云端,出现应用启动后自动关闭、无法写入数据的问题。
初始可正常运行的代码
[FunctionName("EHFunction")] public static async Task Run( [EventHubTrigger("ehquery", Connection = "EventHubConnectionString")] EventData[] events, ILogger log) { var exceptions = new List<Exception>(); foreach (EventData eventData in events) { try { // Read event hub event which contains link to a blob with messages. Read messages from the blob storage endpoint. foreach (var blobEntry in blobData) { foreach (var record in blobEntry.Records) { var recordStr = record.ToString(); log.LogInformation($"Record: {recordStr}"); } } } catch (Exception e) { // We need to keep processing the rest of the batch - capture this exception and continue. // Also, consider capturing details of the message that failed processing so it can be processed again later. log.LogCritical(e.Message); exceptions.Add(e); } } }
新增输出绑定后的问题代码
[FunctionName("EHFunction")] public static async Task Run( [EventHubTrigger("ehquery", Connection = "EventHubConnectionString")] EventData[] events, [EventHub("ehquery-output", Connection = "EventHubOutputConnectionAppSetting")] IAsyncCollector<string> outputEvents, ILogger log) { var exceptions = new List<Exception>(); foreach (EventData eventData in events) { try { // Read event hub event which contains link to a blob with messages. Read messages from the blob storage endpoint. foreach (var blobEntry in blobData) { foreach (var record in blobEntry.Records) { var recordStr = record.ToString(); await outputEvents.AddAsync(recordStr); } } } catch (Exception e) { // We need to keep processing the rest of the batch - capture this exception and continue. // Also, consider capturing details of the message that failed processing so it can be processed again later. log.LogCritical(e.Message); exceptions.Add(e); } } }
云端异常日志
<EventData> <Data>Application 'C:\Program Files (x86)\SiteExtensions\Functions\3.7.1\64bit\' started successfully.</Data> <Data>Process Id: 3776.</Data> <Data>File Version: 13.1.22054.23. Description: IIS ASP.NET Core Module V2 Request Handler. Commit: 509f6badec2f3162f0e50330cd9107e5624b379b</Data> </EventData> </Event> <EventData> <Data>Application 'MACHINE/WEBROOT/APPHOST/EHFunction' has shutdown.</Data> <Data>Process Id: 4624.</Data> <Data>File Version: 13.1.22054.23. Description: IIS ASP.NET Core Module V2 Request Handler. Commit: 509f6badec2f3162f0e50330cd9107e5624b379b</Data> </EventData> </Event>
本地配置参考
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "EventHubConnectionString": "Endpoint=sb://{inputeventhubconnectionstring}", "EventHubOutputConnectionAppSetting": "Endpoint=sb://{outputeventhubconnectionstring}", "FUNCTIONS_WORKER_RUNTIME": "dotnet" } }
问题根因
一共4个核心错误,直接导致函数启动失败、无法写入:
- 配置未同步到云端环境:
local.settings.json仅用于本地开发调试,发布函数时不会自动把该文件内的配置同步到Azure云端的函数应用配置中。云端运行时找不到对应的连接字符串配置,会直接触发启动失败、进程退出。 - 存储配置不适配云端环境:本地配置中
AzureWebJobsStorage的值为UseDevelopmentStorage=true,这是本地Azure存储模拟器的专用配置,云端环境无法访问本地模拟器,函数运行时缺少必须的存储依赖会直接关闭。 - 连接字符串权限/配置不匹配:输出Event Hub的连接字符串需要具备发送权限,如果连接字符串未携带
EntityPath参数,需要确保[EventHub]绑定特性中配置的Hub名称(ehquery-output)和实际目标Event Hub名称完全一致,否则会出现鉴权失败、写入报错。 - 代码逻辑缺失:所有事件处理完成后没有判断收集到的异常列表,也没有触发输出收集器的最终刷新,即使写入过程出现错误也不会触发重试,容易出现消息丢失。
修复方案
- 登录Azure门户,进入目标函数应用的「配置」-「应用程序设置」页面,新增/更新以下配置项:
AzureWebJobsStorage:替换为Azure标准存储账号的连接字符串,不能保留本地开发存储的配置值EventHubConnectionString:填入源Event Hub的连接字符串,确保具备监听权限,建议拼接EntityPath=ehquery参数EventHubOutputConnectionAppSetting:填入目标Event Hub的连接字符串,确保具备发送权限,如果连接字符串未携带EntityPath,确认目标Hub名称和绑定中配置的ehquery-output完全一致
- 补全代码逻辑:在所有事件循环处理完成后,增加异常判断和输出刷新逻辑,参考如下:
// 所有事件循环结束后新增 await outputEvents.FlushAsync(); if (exceptions.Any()) { throw new AggregateException(exceptions); } - 保存配置后重启函数应用,通过实时日志流观察运行状态,确认是否存在剩余的鉴权、网络访问类错误。
内容的提问来源于stack exchange,提问作者Gengis Khan
相关产品推荐
相关产品推荐

