【Azure 应用服务】由 Azure Functions runtime is unreachable 的错误消息推导出 ASYNC(异步)和 SYNC(同步)混用而引起ThreadPool耗尽问题

简介: 【Azure 应用服务】由 Azure Functions runtime is unreachable 的错误消息推导出 ASYNC(异步)和 SYNC(同步)混用而引起ThreadPool耗尽问题

问题描述

在Azure Function Portal上显示: Azure Functions runtime is unreachable,引起的结果是Function App目前不工作,但是此前一直都是正常工作的,且没有对Azure Function做过任何的改动,那它是为什么出现这样的问题呢?

 

问题分析

Azure Functions runtime is unreachable 的错误是 ”Azure Functions 运行时不可访问”,此问题的最常见原因是函数应用失去了对其存储帐户的访问权限。首先我们根据官方文档( 排查错误:“Azure Functions 运行时不可访问” )排查以下每一点:

  1. 存储帐户已被删除
  2. 存储帐户应用程序设置已被删除
  3. 存储帐户凭据无效
  4. 存储帐户不可访问
  5. 每日执行配额已满
  6. 应用受防火墙保护

注:多个Function App之间应尽量避免共享Storage Account,在创建Function App的时候,需要关联独立的Storage Account.

 

在排查完以上每一点后,如果依旧出现 “Azure Functions runtime is unreachable”的问题,那么此时就需要分析当前所运行的Function是否由异常,是否由出现CPU 100%, Memory 100%,以及线程数等情况。

 

在这次的问题中,在Azure Function的日志中,发现大量的如下两种异常:

异常一

Microsoft.Azure.ServiceBus.MessageLockLostException : The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue.

Reference:ae0230de-86a9-xxxx-fdd, TrackingId:eaeef_xxxxxxxxxxxxxxxxxxxx0_B17, SystemTracker:api-11:Topic:inmessage, Timestamp:2021-06-02T06:21:22

   at async Microsoft.Azure.ServiceBus.Core.MessageReceiver.OnRenewLockAsync(String lockToken)

   …..

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

   at async Microsoft.Azure.ServiceBus.MessageReceivePump.RenewMessageLockTask(Message message,CancellationToken renewLockCancellationToken)

与Service Bus相关
异常二

Microsoft.Azure.Storage.StorageException : The lease ID specified did not match the lease ID for the blob.

   at async Microsoft.Azure.Storage.Core.Executor.Executor.ExecuteAsync[T](RESTCommand`1 cmd,IRetryPolicy policy,OperationContext operationContext,CancellationToken token)

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

….

   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

   at async Microsoft.Azure.WebJobs.Host.Timers.TaskSeriesTimer.RunAsync(CancellationToken cancellationToken) at C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Timers\TaskSeriesTimer.cs : 147

与Storage Account相关

 

在异常信息中,并没有明确的指明当前Azure Funciton运行不正常及Azure Functions runtime is unreachable有关的信息。但是Service Bus的 MessageLockLostException 异常值得重点分析,因为MessageLockLostException 异常意味着Function在消费Service Bus的消息的时候,由于处理消息的时间过长,超过了Meesage Lock(锁定,默认30秒),消息无法消费使得回滚会Service Bus的队列中,然后进行下一轮的消费,如此往返。最终表现就是Azure Funciton运行不正常。为了验证这一步,需要收集Function的DUMP文件。PS: 如何获取Windows下Function的DUMP,可参考博文:快速获取DUMP文件(App Service for Windows(.NET/.NET Core): https://www.cnblogs.com/lulight/p/13574331.html

 

检查内存DUMP,确认大量线程(基本上是所有线程)都在等待执行 调用HttpClient上传这一步。而线程池此时已耗尽,无法创建新的线程继续完成Http请求。导致Azure Function运行不正常,无法消费Service Bus中的消息,也引起了 Microsoft.Azure.ServiceBus.MessageLockLostException 异常

(收集DUMP后可使用Visual Studio 2019查看DUMP中的Stack信息)

 

综上,根据DUMP文件中的发现,找到了问题原因:应用程序代码在异步代码调用中使用了Wait方法,导致在Service Bus消息的高峰期间,进程池耗尽,无法正常运行并处理消息,也引起 Azure Functions runtime is unreachable,在最佳的操作要求中,有明确的要求:

在 C# 中,请始终避免引用 Result 属性或在 Task 实例上调用 Wait 方法。 这种方法会导致线程耗尽。

 

解决办法

一:从线程池耗尽的方面入手,增加ThreadPool。在FunctionApp上更改平台配置,改为按照64位模式运行。由于32位的程序(x86)的Function最大线程数位125,而64位修改后,ThreadPool最大值提升到32767。(如果应用打包时target的x86,则需要重新打包应用target x64)。

 

二:修改代码。移除在async方法中所调用的wait()方法,修改位await。PS: 使用异步代码时,里面应该一路使用async和await。

 

 

 

参考资料

排查错误:“Azure Functions 运行时不可访问”: https://docs.azure.cn/zh-cn/azure-functions/functions-recover-storage-account

提高 Azure Functions 的性能和可靠性的最佳做法: https://docs.azure.cn/zh-cn/azure-functions/functions-best-practices#avoid-sharing-storage-accounts

相关文章
|
2月前
|
Java
【Azure 事件中心】向Event Hub发送数据异常 : partitionId[null]: Sending messages timed out
【Azure 事件中心】向Event Hub发送数据异常 : partitionId[null]: Sending messages timed out
|
2月前
|
C# C++ Python
【Azure 应用服务】Azure Durable Function(持久函数)在执行Activity Function时候,因为调用函数名称错误而导致长时间无响应问题
【Azure 应用服务】Azure Durable Function(持久函数)在执行Activity Function时候,因为调用函数名称错误而导致长时间无响应问题
|
2月前
|
Java 开发工具
【事件中心 Azure Event Hub】关于EventHub中出现Error时候的一些问题(偶发错误,EventHub后台升级,用户端错误,Retry机制的重要性)
【事件中心 Azure Event Hub】关于EventHub中出现Error时候的一些问题(偶发错误,EventHub后台升级,用户端错误,Retry机制的重要性)
|
2月前
【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
【Azure Logic App】消费型逻辑应用在消费Service Bus时遇见消息并发速度慢,消息积压
|
2月前
|
JSON 数据格式 Python
【Azure 应用服务】Azure Function Python函数中,如何获取Event Hub Trigger的消息Event所属于的PartitionID呢?
【Azure 应用服务】Azure Function Python函数中,如何获取Event Hub Trigger的消息Event所属于的PartitionID呢?
|
2月前
【Azure 应用服务】Azure Function在执行Function的时候,如果失败了,是否可以重试呢?
【Azure 应用服务】Azure Function在执行Function的时候,如果失败了,是否可以重试呢?
|
2月前
|
消息中间件 存储 Kafka
【Azure 事件中心】适用Mirror Maker生产数据发送到Azure Event Hub出现发送一段时间后Timeout Exception: Expiring 18 record(s) for xxxxxxx: 79823 ms has passed since last append
【Azure 事件中心】适用Mirror Maker生产数据发送到Azure Event Hub出现发送一段时间后Timeout Exception: Expiring 18 record(s) for xxxxxxx: 79823 ms has passed since last append
|
2月前
|
SQL JavaScript 前端开发
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
|
2月前
|
JavaScript 前端开发 API
【Azure 应用服务】Azure Function HTTP 触发后, 230秒就超时。而其他方式触发的Function, 执行5分钟后也超时,如何调整超时时间?
【Azure 应用服务】Azure Function HTTP 触发后, 230秒就超时。而其他方式触发的Function, 执行5分钟后也超时,如何调整超时时间?
|
2月前
|
SQL 网络协议 NoSQL
【Azure 应用服务】App Service/Azure Function的出站连接过多而引起了SNAT端口耗尽,导致一些新的请求出现超时错误(Timeout)
【Azure 应用服务】App Service/Azure Function的出站连接过多而引起了SNAT端口耗尽,导致一些新的请求出现超时错误(Timeout)