使用 Kudu API 使用 serviceBusTrigger 将 azure 函数部署到现有函数应用程序,即使在手动同步触发器后也不会触发

Deploying azure function with serviceBusTrigger to existing function app using Kudu API not triggering even after manually syncing triggers

我有一个现有的函数应用程序,我需要在应用程序中执行用户操作后向其部署 serviceBusTrigger 函数。为此,我一直在使用以下 post

此函数应用程序的 Azure 函数版本 2.0

我目前正在创建一个包含 /function.json 的 zip,使用以下方法posted 到 api/zip 端点

public void CreateAzureFunctionToMonitorQueue(string functionName, string serviceBusQueueName, string path)
    {
        // create zip of new function
        // ZipFile.CreateFromDirectory will create a zip with the directory's name containing the directory's contents
        // so CreateZipOfFunc creates a structure <functionName>/<functionName>/function.json
        // so that the zip contains <functionName>/function.json 
        // which is the required input for api/zip/ from kudu api
        var zipFile = CreateZipOfFunc(functionName, serviceBusQueueName, path);
        var file = File.ReadAllBytes(zipFile);

        MemoryStream stream = new MemoryStream(file);

        using (var client = new HttpClient())
        {
            // deploy zip using Kudu REST api
            client.DefaultRequestHeaders.Add("Authorization", "Basic " + _base64Auth);
            var baseUrl = new Uri($"https://{_webFunctionAppName}.scm.azurewebsites.net/");
            var requestURl = baseUrl + "api/zip/site/wwwroot";
            var httpContent = new StreamContent(stream);
            var response = client.PutAsync(requestURl, httpContent).Result;
        }
        // remove files
        Directory.Delete($"{path}{functionName}", true);
        File.Delete($"{path}{functionName}.zip");
        // deployment using Kudu REST api requires the function triggers to be manually synced
        SyncTriggers();
    }

最后,我 运行 SyncTriggers 手动同步功能应用程序的触发器,因为我读到以这种方式部署需要除 http 之外的所有触发器,在此处找到 https://docs.microsoft.com/en-us/azure/azure-functions/functions-deployment-technologies。我正在使用第二种手动同步触发器的方法。下面是方法

public void SyncTriggers()
    {
        using (var client = new HttpClient())
        {
            var requestUrl = $"https://{_webFunctionAppName}.azurewebsites.net/admin/host/synctriggers?code={_MASTER_KEY}";
            var httpContent = new StringContent("");
            var response = client.PostAsync(requestUrl, httpContent).Result;
        }
    }

两个请求的结果都是成功的,当我在 Azure 门户中查看时,新函数与一个 function.json 文件匹配,当使用 Visual Studio webdeploy 部署时,该文件与工作 serviceBusTrigger 相匹配。

为了对此进行测试,我首先禁用了正在运行的 azure 函数,运行 上面的代码,然后将一条新消息推送到受监视的队列;然而,当消息激活时什么也没有发生。

如果我启用已存在的使用 VS 部署的函数,该函数将触发并处理消息。

现有函数的 function.json 文件如下所示

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-1.0.26",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "serviceBusTrigger",
      "connection": "ServiceBusConnection",
      "queueName": "myqueue",
      "name": "queueItem"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/MyProject.MyLibrary.dll",
  "entryPoint": "MyProject.MyLibrary.MyClass.RunAsync"
}

使用上述方法部署的函数有一个function.json如下

{
  "generatedBy": "Microsoft.NET.Sdk.Functions - 1.0.26",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "serviceBusTrigger",
      "connection": "ServiceBusConnection",
      "queueName": "myqueue",
      "name": "queueItem"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/MyProject.MyLibrary.dll",
  "entryPoint": "MyProject.MyLibrary.MyClass.RunAsync"
}

我是不是漏掉了什么?我的用例是,在创建新队列后,我想创建一个监视 azure 函数来监听它。使用 NameSpaceManager 创建队列工作正常,将消息推送到队列也工作正常。我似乎无法让这个测试用例在我创建一个函数来监视现有队列的地方工作。

可能是当我调用 SyncTrigger 时函数没有注册和正确设置??

谢谢

编辑:我刚看到这个 post https://blogs.msdn.microsoft.com/benjaminperkins/2018/08/07/why-does-my-azure-function-sometimes-stop-being-triggered/ 其中说:

Your endpoint must trigger/bind to only one Azure Function

这是否意味着我只能将一个函数注册到我上传的 dll 中的一个函数?我是否应该使用 function.json 文件上传我想要的入口点方法的副本,并使用不同的名称作为 .csx?

Edit2:这似乎只是与 az fns 绑定资源有关,似乎没有帮助

Edit3:经过大量研究,我生成的 function.json 的 configurationSource 似乎不应该是 "attributes",而是 "config"。现在要测试这个。

Edit4:通过删除 generatedBy 并将我正在生成的 function.json 文件中的 configurationSource 更改为 "config" 来解决问题。

Edit5:删除误导性问题

问题是使用 VS 部署的函数具有 function.json

中的两个属性
"generatedBy": "Microsoft.NET.Sdk.Functions - 1.0.26",
"configurationSource": "attributes",

这实际上只是告诉 azure 函数是从哪里生成的,以及使用作为函数入口点的方法的属性作为配置源。删除 generatedBy 允许在 azure 门户中编辑函数并将 configurationSource 更改为 "config" 告诉 azure 函数运行时使用 function.json 文件进行绑定配置等等。

但是,在 Azure 门户中,我收到一条消息

Error:

Function (MyFunction) Error: Configuration error: all functions in D:\home\site\wwwroot\bin\MyProject.MyLibrary.dll must have the same value for 'configurationSource'.
Session Id: MY_SESSION_ID

Timestamp: 2019-06-30T21:04:22.709Z

我部署的函数仍然有效,部署函数调用的其他具有 http 绑定的现有函数仍然有效(它们有 function.json 由 Skd.Functions 和 configurationSource 生成的文件:"attributes",所以目前这似乎不是成败错误;但是,我将更改我的部署,以便所有人都具有 configurationSource:"config"

所以将输出 function.json 更改为

{
  "configurationSource": "config",
  "bindings": [
    {
      "type": "serviceBusTrigger",
      "connection": "ServiceBusConnection",
      "queueName": "myqueue",
      "name": "queueItem"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/MyProject.MyLibrary.dll",
  "entryPoint": "MyProject.MyLibrary.MyClass.RunAsync"
}

解决了我的问题