我有一个 http 触发的 azure 函数,可以启动协调器函数。在我的开发租户中,代码运行没有问题,但在部署到另一个租户时,在影响 azure 功能的安全设置方面除了麻烦之外什么也没有。
现在我们可以通过VPN连接到公司网络时调用http触发,并且http触发功能运行没有问题。在日志中我们可以看到 Orchestrator 功能启动,但立即失败。
我们已经测试了能够连接到存储帐户,并且我们尝试删除除了日志语句之外的编排器内的所有代码。但还是失败了。
Azure 门户中是否有一些设置可能仅影响协调器,而不影响 Http 触发的功能?
[FunctionName(nameof(PlannerOrchestrator))]
public async Task<string> PlannerOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
log.LogInformation("Starting orchestration for Planner request");
return string.Empty;
}
[FunctionName(nameof(PostPlannerTask))]
public async Task<IActionResult> PostPlannerTask(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
[DurableClient] IDurableClient client,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var incomingAccessToken = req.Headers.TryGetValue("Authorization", out var tokenHeaderValue) ? tokenHeaderValue.FirstOrDefault()?.Replace("Bearer ", string.Empty) : null;
try
{
bool validToken = ValidateToken(incomingAccessToken);
log.LogInformation("Valid token: {validToken}", validToken);
if (!validToken)
{
return new UnauthorizedResult();
}
}
catch (Exception ex)
{
log.LogError("Invalid token: {ex}", ex.Message);
return new BadRequestResult();
}
var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var plannerRequest = JsonConvert.DeserializeObject<PlannerRequest>(requestBody);
log.LogInformation("Request received: {request}", requestBody);
var instanceId = nameof(PlannerOrchestrator) + "-" + Guid.NewGuid();
instanceId = await client.StartNewAsync(nameof(PlannerOrchestrator), instanceId, plannerRequest);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromSeconds(60));
}
检查
LogStream=>App Insights Logs
中的错误日志:
使用以下查询检查MSDOC中提到的与Durable功能相关的错误日志:
let orchestrationInstanceID = "XXXXXX";
let start = datetime(XXXX-XX-XXTXX:XX:XX);
traces
| where timestamp > start and timestamp < start + 1h
| extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] )
| extend logLevel = customDimensions["LogLevel"]
| extend functionName = customDimensions["prop__functionName"]
| extend status = customDimensions["prop__status"]
| extend details = customDimensions["prop__Details"]
| extend reason = customDimensions["prop__reason"]
| where severityLevel > 1 // to see all logs of severity level "Information" or greater.
| where instanceId == orchestrationInstanceID
| sort by timestamp asc
我已将您的代码部署到 Azure 函数应用程序,并且能够按预期运行该函数。
代码片段:
public static async Task<IActionResult> PostPlannerTask(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req,
[DurableClient] IDurableClient client,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var incomingAccessToken = req.Headers.TryGetValue("Authorization", out var tokenHeaderValue) ? tokenHeaderValue.FirstOrDefault()?.Replace("Bearer ", string.Empty) : null;
try
{
bool validToken = ValidateToken(incomingAccessToken);
log.LogInformation("Valid token: {validToken}", validToken);
if (!validToken)
{
return new UnauthorizedResult();
}
}
catch (Exception ex)
{
log.LogError("Invalid token: {ex}", ex.Message);
return new BadRequestResult();
}
var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
var plannerRequest = JsonConvert.DeserializeObject<PlannerRequest>(requestBody);
log.LogInformation("Request received: {request}", requestBody);
var instanceId = nameof(Function1) + "-" + Guid.NewGuid();
instanceId = await client.StartNewAsync(nameof(Function1), instanceId, plannerRequest);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return await client.WaitForCompletionOrCreateCheckStatusResponseAsync(req, instanceId, TimeSpan.FromSeconds(60));
}
private static bool ValidateToken(string token)
{
return !string.IsNullOrEmpty(token);
}
耐用功能:
[FunctionName("Function1")]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));
return outputs;
}
[FunctionName(nameof(SayHello))]
public static string SayHello([ActivityTrigger] string name, ILogger log)
{
log.LogInformation("Saying hello to {name}.", name);
return $"Hello {name}!";
}
[FunctionName("Function1_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
string instanceId = await starter.StartNewAsync("Function1", null);
log.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);
return starter.CreateCheckStatusResponse(req, instanceId);
}
部署到Azure功能应用程序。
传送门:
运行函数时在Auth部分提供承载令牌:
回复: