【问题标题】:Same method in Azure Function takes longerAzure Function 中的相同方法需要更长的时间
【发布时间】:2017-12-12 14:17:12
【问题描述】:

我很好奇将密集方法移至 Azure 函数时响应时间会改善多少。 所以我创建了 2 个小应用程序。第一个是 ASP.NET MVC 应用程序(应用服务计划 S1)。第二个是 ASP.NET MVC 应用程序,具有 1 个 Azure Function(在 Function 项目中)、应用服务计划 S1 以及 FunctionApp 的消费计划。

这两个应用程序都是相同的,除了 1 个方法,它被移动到一个 Azure 函数,MergeDocumentsAndExport。 在我的应用程序中,在应用程序启动时会创建给定数量的 Document 记录。

public class Document {
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public byte[] Content { get; set; }
    public DateTime DateCreated { get; set; }
}

最终用户可以通过单击视图中的按钮下载数据库中的所有Documents。单击此按钮时,将调用方法MergeDocumentsAndExport

没有 Azure 函数

public byte[] MergeDocumentsAndExport()
{
    var startmoment = DateTime.Now;
    var baseDocument = new Spire.Doc.Document();
    var documents = _documentDataService.GetAllDocuments();

    foreach (var document in documents)
    {
        using (var memoryStream = new MemoryStream(document.Content))
        {
            var documentToLoad = new Spire.Doc.Document();
            documentToLoad.LoadFromStream(memoryStream, FileFormat.Doc);

            foreach (Section section in documentToLoad.Sections)
            {
                baseDocument.Sections.Add(section.Clone());
            }
        }
    }

    byte[] byteArrayToReturn;

    using (var memoryStream = new MemoryStream())
    {
        baseDocument.SaveToStream(memoryStream, FileFormat.Doc);
        byteArrayToReturn = memoryStream.ToArray();
    }

    _responseLogger.Log(startmoment, DateTime.Now, nameof(MergeDocumentsAndExport);
    return byteArrayToReturn;
}

_responseLogger.Log(..) 方法记录方法的开始和结束,方法名称决定执行时间(也许responselogger 不是该服务的最佳名称)。

使用 Azure 函数

同样的方法被转换成一个 HTTP 触发的 Azure 函数。

[DependencyInjectionConfig(typeof(DependencyConfig))]
public static class MergeDocumentsAndExportFunction
{
    [FunctionName("MergeDocumentsAndExportFunction")]
    public static HttpResponseMessage Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "MergeDocumentsAndExport")]HttpRequestMessage req,
        TraceWriter log,
        [Inject]IDocumentDataService documentDataService,
        [Inject]IResponseLogger responseLogger)
    {
        var startmoment = DateTime.Now;
        log.Info("MergeDocumentsAndExportFunction processed a request.");

        var baseDocument = new Document();
        var documents = documentDataService.GetAllDocuments();

        foreach (var document in documents)
        {
            using (var memoryStream = new MemoryStream(document.Content))
            {
                var documentToLoad = new Document();
                documentToLoad.LoadFromStream(memoryStream, FileFormat.Doc);

                foreach (Section section in documentToLoad.Sections)
                {
                    baseDocument.Sections.Add(section.Clone());
                }
            }
        }

        using (var memoryStream = new MemoryStream())
        {
            baseDocument.SaveToStream(memoryStream, FileFormat.Doc);
            // Create response to send document as byte[] back.
            var response = req.CreateResponse(HttpStatusCode.OK);
            var buffer = memoryStream.ToArray();
            var contentLength = buffer.Length;
            response.Content = new StreamContent(new MemoryStream(buffer));
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/ms-word");
            response.Content.Headers.ContentLength = contentLength;

            responseLogger.Log(startmoment, DateTime.Now, "MergeDocumentsAndExport");
            return response;
        }
    }

MergeDocumentsAndExportFunction 中添加了一些代码,例如创建和返回HttpResponseMessage。我没有实现异步调用,因为它只是为了这个小测试,我想比较两个环境中方法MergeDocumentsAndExport的同步执行时间。

我得到的结果不是我所期望的。在几乎所有情况下,Azure 函数的执行时间都差不多或更长。我知道 Azure 函数有一个启动时间,我排除了这些时间。也许是因为 Autofac 的依赖注入可能需要一些时间?合并和导出数据库中的 1000 个文档时的结果(以秒为单位):

没有 Azure 功能:

  • 49,34
  • 50,21
  • 51,26
  • 49,00
  • 50,21
  • 50,68
  • ...等等... 平均:49.69 秒。

使用 Azure 功能:

  • 133,64(启动,排除)
  • 77,68
  • 85,18
  • 66,46
  • 86,00
  • 65,17
  • ...等等... 平均:82.69 秒。

同一方法在不同环境中的执行时间可能会相差 30 秒,将 1000 个文档合并为 1 个。Azure Function 执行时间怎么可能更长(+ 30 秒)?是不是因为我用错了?谢谢。

【问题讨论】:

    标签: c# asp.net-mvc azure azure-functions


    【解决方案1】:

    Azure Functions on Consumption Plan 不太适合改善长时间运行的 CPU 密集型工作负载的响应时间。

    根据我的观察,这些实例的性能相当适中,因此与固定计划的应用服务相比,请求持续时间可能不会下降。

    函数的优势在于具有小吞吐量或可变吞吐量的短期执行。

    如果您仍想比较,您可以在 Fixed App Service 计划中部署相同的 Function App,测量那里的时间,然后选择最适合您的。

    【讨论】:

      【解决方案2】:

      如果使用计划中的 Azure 函数处于空闲状态,它会从主机释放保留的计算。当一个新请求到来时,函数需要一些时间来启动并请求新的计算。

      您可以设置功能以使用应用服务计划和“始终开启”设置而不是消费计划,它应该会更快。 https://docs.microsoft.com/en-us/azure/azure-functions/functions-scale

      【讨论】:

      • 是的,但我读到 Azure 函数在 10 分钟后空闲。我在完成后立即启动了该功能。那还适用吗?
      • 不,那么您不应该受到冷启动的影响。使用消费计划的函数应用也在 Azure Files 上运行,它本身很慢。github.com/Azure/azure-webjobs-sdk-script/issues/1626
      • 您可以激活 Application Insight 以查看它是否能找到需要这么长时间的问题,azure.microsoft.com/sv-se/updates/…。无论如何,我认为您的代码本身不会造成延迟。
      猜你喜欢
      • 1970-01-01
      • 2022-04-28
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 1970-01-01
      相关资源
      最近更新 更多