我们有一个网络作业项目,它是一个基于计时器的项目。它在本地运行(在 VS2022 调试器中离线),但我们使用 devops 构建为 linux 目标“--runtime linux-x64”并部署到 App_Data/jobs/triggered/Jobnamefolder/appfiles,部署时它似乎没有运行,或者至少没有证据表明该作业存在 - 它没有显示在网络作业页面上 - 稍后会详细介绍。
工作基本上如下:
using My.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace My.WebJobs
{
class Program
{
static async Task Main()
{
var host = new HostBuilder()
.ConfigureWebJobs(webJobsBuilder =>
{
webJobsBuilder.AddTimers();
})
.ConfigureAppConfiguration((context, configBuilder) =>
{
configBuilder.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureLogging((context, b) =>
{
b.AddConsole();
})
.ConfigureServices((context, services) =>
{
var configuration = context.Configuration;
var connectionString = configuration["ConnectionStrings:DefaultConnection"];
services.AddDbContext<DatabaseService>(options =>
{
options.UseSqlServer(connectionString);
});
})
.Build();
using (host)
{
await host.RunAsync();
}
}
}
}
和
using Azure;
using Azure.Communication.Email;
using My.Data;
using My.Domain;
using Microsoft.Azure.WebJobs;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
namespace My.WebJobs
{
public class Functions
{
private readonly DatabaseService _databaseService;
public Functions(DatabaseService databaseService)
{
_databaseService = databaseService;
}
public void TimerTriggeredFunction([TimerTrigger("0 */1 * * * *")] TimerInfo timerInfo, ILogger logger)
{
logger.LogInformation($"Function executed at: {DateTime.Now}");
SendFeedbackEmails(logger).Wait();
}
// this attribute defines what function will be triggered by the web job
[NoAutomaticTrigger]
public async Task SendFeedbackEmails(ILogger logger)
{
...
}
}
}
我有 2 个函数,一个是 TimerTrigger,另一个用 NoAutomaticTrigger 标记,因为它不称为 Run。
我们还有一个带有“时间表”的“settings.job”:{“0 * * * * *”}
我们的网站运行良好,但网络作业从未运行。 我可以通过 SSH 登录该站点并确认文件位于文件夹中,并且日志流也显示它们正在复制。 日志不会显示与 webjob 相关的任何内容,除非我们转到 Azure Portal webjobs 页面,在这种情况下会发生后台异常:
2024-07-09T00:20:23.0533898Z Exception StackTrace : at Kudu.Services.Diagnostics.HttpRequestExtensions.ForwardToContainer(String route, HttpRequestMessage request) in /tmp/KuduLite/Kudu.Services/Diagnostics/HttpRequestExtensions.cs:line 22
2024-07-09T00:20:23.0725163Z at Kudu.Services.Jobs.JobsController.ForwardJobRequestToContainer(String route) in /tmp/KuduLite/Kudu.Services/Jobs/JobsController.cs:line 200
2024-07-09T00:20:23.0725763Z at Kudu.Services.Jobs.JobsController.ListAllJobs() in /tmp/KuduLite/Kudu.Services/Jobs/JobsController.cs:line 28
2024-07-09T00:20:23.0725790Z at lambda_method132(Closure , Object , Object[] )
2024-07-09T00:20:23.0725821Z at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
2024-07-09T00:20:23.0725850Z at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
2024-07-09T00:20:23.0725876Z at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
2024-07-09T00:20:23.0725962Z at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
2024-07-09T00:20:23.0725984Z --- End of stack trace from previous location ---
2024-07-09T00:20:23.0726010Z at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
2024-07-09T00:20:23.0726036Z at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
2024-07-09T00:20:23.0726059Z at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
2024-07-09T00:20:23.0732366Z --- End of stack trace from previous location ---
2024-07-09T00:20:23.0732406Z at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
2024-07-09T00:20:23.0732430Z at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
2024-07-09T00:20:23.0732456Z at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
2024-07-09T00:20:23.0732502Z at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
2024-07-09T00:20:23.0732529Z --- End of stack trace from previous location ---
2024-07-09T00:20:23.0732555Z at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
2024-07-09T00:20:23.0732582Z at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
2024-07-09T00:20:23.0732604Z at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
2024-07-09T00:20:23.0732630Z at Kudu.Services.Web.Tracing.TraceMiddleware.Invoke(HttpContext context) in /tmp/KuduLite/Kudu.Services.Web/Tracing/TraceMiddleware.cs:line 107
2024-07-09T00:20:23.1611928Z [41m[30mfail[39m[22m[49m: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
2024-07-09T00:20:23.1612508Z An unhandled exception has occurred while executing the request.
2024-07-09T00:20:23.1612536Z System.Net.Http.HttpRequestException: Connection refused (169.254.130.5:50555)
2024-07-09T00:20:23.1626364Z ---> System.Net.Sockets.SocketException (111): Connection refused
2024-07-09T00:20:23.1626787Z at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 )
2024-07-09T00:20:23.1626817Z at System.Net.Sockets.Socket.<ConnectAsync>g__WaitForConnectWithCancellation|277_0(AwaitableSocketAsyncEventArgs , ValueTask , CancellationToken )
2024-07-09T00:20:23.1626843Z at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String , Int32 , HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1626866Z --- End of inner exception stack trace ---
2024-07-09T00:20:23.1626891Z at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String , Int32 , HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1626917Z at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1626946Z at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1626971Z at System.Net.Http.HttpConnectionPool.AddHttp11ConnectionAsync(HttpRequestMessage )
2024-07-09T00:20:23.1627045Z at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken )
2024-07-09T00:20:23.1627071Z at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1627096Z at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage , Boolean , Boolean , CancellationToken )
2024-07-09T00:20:23.1627122Z at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1627147Z at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage , Boolean , CancellationToken )
2024-07-09T00:20:23.1627177Z at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage , HttpCompletionOption , CancellationTokenSource , Boolean , CancellationTokenSource , CancellationToken )
2024-07-09T00:20:23.1627203Z at Kudu.Services.Web.Tracing.TraceMiddleware.Invoke(HttpContext context) in /tmp/KuduLite/Kudu.Services.Web/Tracing/TraceMiddleware.cs:line 107
2024-07-09T00:20:23.1627229Z at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware.InvokeCore(HttpContext context)
2024-07-09T00:20:23.1627256Z at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
似乎没有文档完全说明网络作业“如何”运行 - 即什么托管应用程序或启动它。
关于如何诊断超越这一点有什么想法吗?我们所拥有的有明显错误吗?
谢谢!
编辑:管道构建和打包如下:
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/My.WebJobs.csproj'
arguments: '--output $(Build.BinariesDirectory)/publish_output/App_Data/jobs/triggered/My-WebJob --runtime linux-x64'
zipAfterPublish: false
modifyOutputPath: false
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/My.WebApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.BinariesDirectory)/publish_output --runtime linux-x64'
zipAfterPublish: false
modifyOutputPath: false
部署到App_Data/jobs/triggered/Jobnamefolder/appfiles,部署后它似乎没有运行
App_Data/jobs/triggered/<JobName>
目录中,而不是像 appfiles
这样的子目录中。对于 Linux 部署,您需要
run.sh
脚本而不是 run.cmd
。
检查以下
azure-pipeline.yaml
文件进行部署。
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '6.x.x'
installationPath: $(Agent.ToolsDirectory)/dotnet
- script: |
dotnet build --configuration Release --output $(Build.ArtifactStagingDirectory)/webjob
displayName: 'Build WebJob'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)/webjob'
artifactName: 'webjob'
- task: AzureRmWebAppDeployment@4
inputs:
azureSubscription: 'AzureSubscription'
appType: 'webApp'
WebAppName: 'YourWebAppName'
packageForLinux: '$(Build.ArtifactStagingDirectory)/webjob'
RuntimeStack: 'DOTNETCORE|6.0'
状态:
结果:
修改/更新答案
运行.sh:
#!/bin/bash
# This is the command to start your .NET Core WebJob
dotnet My.WebJobs.dll
run.sh
脚本是否具有可执行权限。chmod +x /home/site/wwwroot/App_Data/jobs/triggered/My-WebJob/run.sh
项目结构:
App_Data/
└── jobs/
└── triggered/
└── My-WebJob/
├── My.WebJobs.dll
├── run.sh
└── settings.job