Я использую изолированные функции Azure и SQL Server с Entity Framework. Это конфигурация, которую я имею внутри моего Program.cs соответствующего приложения-функции Azure:
var connectionString = Configuration.GetConnectionString("AzureSQL");
services.AddDbContext<ReportDataDbContext>(options =>
{
options
.UseSqlServer(connectionString)
.EnableSensitiveDataLogging(queryParamsLogging);
});
Моей функции Azure назначен UserManagedIdentity, и мой SQL Server также назначил этот UserManagedIdentity. Из моего конвейера в Azure DevOps я пытаюсь применить миграцию через HTTP-запрос к функции Azure.
displayName: 'Applying Migrations EF'
inputs:
pwsh: true
targetType: inline
script: |
$env = "${{ parameters.env }}"
# step 1 receive auth token to call az function
$applyMigrationFunctionUrl = "https://api-$env.azazello.pl/${{ parameters.apiTypeUrl }}/migrations/apply/${{ parameters.apiTypeUrl }}"
echo "Receiving application token..."
$body = @{
client_id = "${{ parameters.clientId }}"
scope = "${{ parameters.authAllowedAudience }}/.default"
client_secret = "${{ parameters.secretId}}"
grant_type = "client_credentials"
}
$tenantId = "${{ variables.tenantId }}"
$azToken = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body | Select-Object -ExpandProperty access_token
echo "Token received."
$headers = @{
'Authorization' = "Bearer $azToken"
}
# step 2 call apply migrations endpoint of corresponding az-function
$response = Invoke-RestMethod -ConnectionTimeoutSeconds 180 -OperationTimeoutSeconds 180 -RetryIntervalSec 20 -MaximumRetryCount 3 -Uri $applyMigrationFunctionUrl -Method Post -Headers $headers
Код конечной точки:
[Function(nameof(ApplyMigrationsAllReporting))]
public async Task<IActionResult> ApplyMigrationsAllReporting(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "migrations/apply/api/reporting")]
HttpRequest httpRequest,
CancellationToken cancellationToken)
{
_logger.LogWarning(
"[ApplyMigrationsAllReporting] Applying all pending migrations. CancellationToken: {CancellationToken}", cancellationToken);
await _dbContext.Database.MigrateAsync(cancellationToken);
return new OkResult();
}
Проблема в том, что время от времени после развертывания первый запрос может завершиться ошибкой со следующей ошибкой:
System.Threading.Tasks.TaskCanceledException:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection+<OpenInternalAsync>d__70.MoveNext (Microsoft.EntityFrameworkCore.Relational, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection+<OpenInternalAsync>d__70.MoveNext (Microsoft.EntityFrameworkCore.Relational, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection+<OpenAsync>d__66.MoveNext (Microsoft.EntityFrameworkCore.Relational, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator+<>c__DisplayClass20_0+<<ExistsAsync>b__0>d.MoveNext (Microsoft.EntityFrameworkCore.SqlServer, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator+<>c__DisplayClass20_0+<<ExistsAsync>b__0>d.MoveNext (Microsoft.EntityFrameworkCore.SqlServer, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy+<ExecuteAsync>d__7`2.MoveNext (Microsoft.EntityFrameworkCore.SqlServer, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository+<ExistsAsync>d__24.MoveNext (Microsoft.EntityFrameworkCore.Relational, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator+<MigrateAsync>d__15.MoveNext (Microsoft.EntityFrameworkCore.Relational, Version=8.0.5.0, Culture=neutral, PublicKeyToken=adb9793829ddae60)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Test.Azure.ReportApi.Http.DbMigrationFunctions+<ApplyMigrationsAllReporting>d__3.MoveNext (Test.Azure.ReportApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: D:\a\1\s\ReportApi\Test.Azure.ReportApi\Http\DbMigrationsFunctions.cs:32)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Test.Azure.ReportApi.DirectFunctionExecutor+<ExecuteAsync>d__3.MoveNext (Test.Azure.ReportApi, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null: D:\a\1\s\ReportApi\Test.Azure.ReportApi\obj\Release\net8.0\Microsoft.Azure.Functions.Worker.Sdk.Generators\Microsoft.Azure.Functions.Worker.Sdk.Generators.FunctionExecutorGenerator\GeneratedFunctionExecutor.g.cs:50)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware+<Invoke>d__0.MoveNext (Microsoft.Azure.Functions.Worker.Core, Version=1.18.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c: D:\a\_work\1\s\src\DotNetWorker.Core\OutputBindings\OutputBindingsMiddleware.cs:13)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.FunctionsHttpProxyingMiddleware+<Invoke>d__4.MoveNext (Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore, Version=1.2.1.0, Culture=neutral, PublicKeyToken=551316b6919f366c: D:\a\_work\1\s\extensions\Worker.Extensions.Http.AspNetCore\src\FunctionsMiddleware\FunctionsHttpProxyingMiddleware.cs:48)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e)
at Microsoft.Azure.Functions.Worker.FunctionsApplication+<InvokeFunctionAsync>d__10.MoveNext (Microsoft.Azure.Functions.Worker.Core, Version=1.18.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c: D:\a\_work\1\s\src\DotNetWorker.Core\FunctionsApplication.cs:89)
Моя строка подключения:
Server=tcp:sqlMy,1433;Authentication=Active Directory Default;Encrypt=True;User Id=GUID_OF_UserManagedIdentity;Database=MyDb;MultipleActiveResultSets=True;Connection Timeout=60;TrustServerCertificate=True
Я добавил повтор в powershell invoke-restmethod (код выше в powershell), и с повтором в сумме все работает нормально -> первый запрос может спорадически завершаться неудачно, но при повторной попытке второй запрос (следующая попытка с полностью теми же данными) выполняется успешно. Итак, с БД соединение в порядке. UserManagedIdentity и соответствующий пользователь в базе данных имеют все необходимые роли (db_reader, db_writer, ddl_admin).
Цель: я хотел бы избежать этой повторной попытки в PowerShell и понять, почему эта задача отменяется, когда я пытаюсь перенести базу данных, даже если нет ожидающих миграции, просто время от времени происходит сбой после развертывания...
Это начало происходить, когда я попытался использовать аутентификацию без пароля, до этого я использовал аутентификацию sql, и все было в порядке.
Нашел похожую тему, но без ответа :( :
Я ценю любую помощь и советы!
Привет! Могу ли я узнать, воспроизводится ли проблема, если вы запускаете сценарий через локальный PowerShell, а не в задаче конвейера PowerShell? Это может помочь выявить причину проблемы. Спасибо.
@AlvinZhao-MSFT нет, это невозможно воспроизвести повторно
А что, если добавить немного времени на ожидание, например Start-Sleep -s 30, как предложил @SvyatlavDanyliv?
@AlvinZhao-MSFT Я пробовал даже 10 минут :) не помогает(
Ваш сценарий PowerShell просто генерирует токен в качестве заголовка запроса API, а затем вызывает API-функцию, верно? Есть ли какие-либо ошибки в журналах конвейера?
@AlvinZhao-MSFT да, именно. ошибка в конвейере перед повторной попыткой была просто: «Ошибка вызова-restmethod», после повторной попытки ошибок в конвейере не было. Но в логах лазури всегда было и есть "задача отменена"
Это было так странно, что простой вызов API мог завершиться неудачно, и это происходило только тогда, когда запрос был отправлен из среды агента. Я действительно не был уверен, связана ли проблема с тем, с какой машины был отправлен запрос. Если этот вызов API был просто для запуска функции, заметили ли вы, что функция была запущена или вообще не была запущена? По моему мнению, ошибка указывала на то, что функция была запущена, и после этого рабочий процесс в этой функции каким-то образом не смог подключиться к базе данных SQL. Если это так, то каковы были состояния функции и ресурсов SQL в момент возникновения проблемы?





Я также столкнулся с аналогичной проблемой с TaskCanceledException в моем проекте. Второй вариант ниже помог мне решить мое дело. Обращаясь к этой проблеме, вы можете попробовать несколько способов решить свою проблему:
Попробуйте удалить все пакеты, на которые есть ссылки Microsoft.Extensions.*, если вы не используете интеграцию ASP.NET Core в своих изолированных функциях.
Если вы используете интеграцию ASP.NET Core, попробуйте добавить <PublishReadyToRun>true</PublishReadyToRun> и <RuntimeIdentifier>linux-x64</RuntimeIdentifier> или <RuntimeIdentifier>win-x64</RuntimeIdentifier> в файл *.csproj вашего проекта функции Azure.
да, мне помог 2 пункт, спасибо но это было очень странно........
Вероятно, потому, что миграция занимает некоторое время, а HTTP-запрос по умолчанию имеет тайм-аут 30 секунд.