CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载导读OrchardCore.BackgroundTasks是 Orchard Core 中负责后台任务Background Tasks注册、调度与管理的模块。启用该功能后你可以在管理后台的Tools → Background Tasks页面查看系统中所有已注册的后台任务并逐个或批量启用/禁用、修改其 cron 调度表达式以及决定任务是否需要构建租户路由管线以便在后台生成正确 URL。读完本文你将掌握该模块的完整使用方式、任务注册与调度原理并能基于IBackgroundTask接口编写自定义后台任务。模块概览它能做什么根据模块的官方文档与模块清单声明该模块的核心职责是为管理后台任务提供工具具体表现为提供一个管理后台 UI展示所有已注册的后台任务支持启用 / 禁用某个任务支持修改任务的调度计划即运行频率使用 cron 表达式 语法支持配置是否构建租户路由管线tenant pipeline使任务在后台执行时能够生成正确的路由 URL。该模块在清单中被归类为Tasks任务类别模块显示名为 Background Tasks。在 Orchard Core 中后台任务 是框架级能力任何一个实现了IBackgroundTask的服务都会被框架的托管服务周期性发现并执行详见下文调度与执行原理。本模块提供的则是可视化管理这些任务的手段——调度引擎本身位于框架核心ModularBackgroundService管理 UI 与设置持久化位于本模块。启用功能与管理入口启用模块在 Orchard Core 站点中通过管理后台的Configuration → Features页面启用Background Tasks功能模块即可。启用后模块会通过其 Startup.cs 注册以下服务services .AddScopedBackgroundTaskManager() // 任务设置文档的读写管理 .AddPermissionProviderPermissions() // 权限提供程序 .AddNavigationProviderAdminMenu() // 后台导航菜单 .AddScopedIBackgroundTaskSettingsProvider, BackgroundTaskSettingsProvider();菜单入口Tools → Background Tasks依据 AdminMenu.cs管理入口按导航格式分为两种新格式Tools → Background Tasks旧格式LegacyConfiguration → Tasks → Background Tasks当NavigationHelper.UseLegacyFormat()返回 true 时使用。该菜单项受ManageBackgroundTasks权限保护并且是LocalNav本地导航仅在模块功能启用时显示。权限定义见 Permissions.cspublic static readonly Permission ManageBackgroundTasks new(ManageBackgroundTasks, Manage background tasks);该权限默认授予Administrator管理员角色。路由与权限校验管理页面由 BackgroundTaskController 提供其路由模板为BackgroundTasks/{action}/{name?}。控制器在Index、Edit、Enable、Disable等所有操作入口处均先执行_authorizationService.AuthorizeAsync(User, Permissions.ManageBackgroundTasks)未授权用户将被拒绝Forbid。管理界面任务列表与批量操作任务列表页进入Tools → Background Tasks后Index.cshtml 会渲染一个任务列表每项包含任务标题可点击进入编辑页任务描述若有Edit按钮根据当前启用状态显示Disable红色或Enable绿色按钮。列表页顶部还提供搜索框按标题或描述进行不区分大小写的模糊匹配见控制器的Index方法中对options.Search的处理状态筛选Enabled已启用/Disabled已禁用两种筛选条件批量操作Bulk Actions勾选多个任务后可批量Enable启用或Disable禁用。批量操作的实现位于控制器的IndexBulkActionPOST方法对每个勾选的任务名称加载或创建其设置按BackgroundTaskBulkAction.Enable/Disable置Enable布尔值再调用BackgroundTaskManager.UpdateAsync持久化并给出操作成功的通知。列表中展示的任务来源控制器通过IEnumerableIBackgroundTask _backgroundTasksDI 注入的所有后台任务实现逐一获取其默认设置task.GetDefaultSettings()若该任务在持久化文档中存在自定义设置则优先展示持久化值。列表的排序与分页列表按任务标题排序并使用框架的Pager组件进行分页PagerOptions控制每页条数等满足任务数量较多时的浏览需求。编辑任务设置Properties 与 Advanced 两个页签点击任务的Edit按钮进入编辑页Edit.cshtml页面分为两个页签Properties属性字段说明Title任务显示名称来自任务类上的BackgroundTaskAttribute.Title只读不可修改Description任务描述可编辑保存后会覆盖默认描述Schedule任务的调度计划即 cron 表达式可编辑旁边提供Reset Schedule按钮一键恢复为任务类声明的默认调度Use Tenant Pipeline勾选后任务执行前会构建并执行租户管线tenant pipeline使后台任务能够正确配置端点并生成路由 URL。Reset Schedule 按钮的前端逻辑见 background-task-edit.ts点击后将隐藏字段DefaultSchedule即任务类声明的默认 cron回填到调度输入框。Advanced高级字段说明Lock timeout (ms)执行任务前尝试获取分布式锁的超时时间毫秒。设为0表示不使用锁Lock expiration (ms)获取到的锁的过期时间毫秒。设为0表示不使用锁两个字段的提示文案明确说明如果未启用分布式锁功能这两个设置将被忽略。当两者都大于 0 时任务被视为原子任务atomic见 BackgroundTaskSettings.cs 中的IsAtomic属性并受分布式锁保护详见下文原子执行与分布式锁。保存逻辑提交编辑表单后控制器Edit(POST)会校验模型随后加载可变文档将Schedule去除首尾空白、Description、LockTimeout、LockExpiration、UsePipeline写回设置并调用BackgroundTaskManager.UpdateAsync持久化Title始终以任务类声明的默认值为准settings.Title defaultSettings.Title。编写自定义后台任务核心接口IBackgroundTask任何后台任务只需实现 IBackgroundTask.cs 中的唯一方法public interface IBackgroundTask { Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken); }serviceProvider是当前**租户作用域tenant scope**的服务提供者任务实现可以通过它解析所需服务如ISiteService、自定义业务服务等。用BackgroundTaskAttribute声明默认配置任务类可标注 BackgroundTaskAttribute.cs声明任务的显示名称、默认启用状态、默认调度、描述、锁参数与管线选项[AttributeUsage(AttributeTargets.Class, AllowMultiple false, Inherited true)] public sealed class BackgroundTaskAttribute : Attribute { public string Title { get; set; } // 显示名称 public bool Enable { get; set; } true; // 默认启用 public string Schedule { get; set; } */5 * * * *; // 默认调度cron public string Description { get; set; } string.Empty; public int LockTimeout { get; set; } // 0 不加锁 public int LockExpiration { get; set; } // 0 不加锁 public bool UsePipeline { get; set; } // 是否构建租户管线 }这些默认值通过 BackgroundTaskExtensions.GetDefaultSettings 反射读取生成BackgroundTaskSettings。任务的技术名称Name即其类型的完整类名GetType().FullName这也是管理 UI 中用于唯一标识任务的键。若任务类未标注该特性则默认设置仅包含技术名称与标题标题回退为技术名。真实任务示例仓库中有大量内置后台任务可作为编写参考媒体分片上传清理ChunkFileUploadBackgroundTask.cs每天零点0 0 * * *清理废弃的分片上传临时目录内容索引更新ContentIndexingBackgroundTask.cs每分钟* * * * *同步更新搜索索引中的内容项并声明了LockTimeout 1000、LockExpiration 300000审计日志清理AuditTrailBackgroundTask.cs每天零点0 0 * * *按保留天数清理过期审计事件。以内容索引任务为例其完整写法[BackgroundTask( Title Indexes Content Updater, Schedule * * * * *, Description Periodically synchronizes and updates all modified content items in the search indexes to ensure search results remain current., LockTimeout 1000, LockExpiration 300000)] public sealed class ContentIndexingBackgroundTask : IBackgroundTask { public Task DoWorkAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken) { var indexingService serviceProvider.GetRequiredServiceContentIndexingService(); return indexingService.ProcessRecordsForAllIndexesAsync(); } }提示Enable默认值为true即任务默认启用Schedule的默认值在特性上为*/5 * * * *每 5 分钟而在BackgroundTaskSettings类上为* * * * *每分钟。实际生效的调度以管理界面中保存的设置持久化文档为准未保存过设置时则回退到特性声明的默认值。调度与执行原理调度器BackgroundTaskScheduler框架核心在 BackgroundTaskScheduler.cs 中为租户 任务维护一个调度器实例核心判定逻辑CanRun()取当前 UTC 时间与参照时间ReferenceTime若站点配置了时区TimeZone ! null将两者转换到该时区再比较使用NCrontab库解析Settings.Schedule计算GetNextOccurrence(referenceTime)若当前时间已到达下一次执行点且Settings.Enable !Released Updated均成立则返回true可执行否则推进ReferenceTime并返回false。也就是说任务是否触发由cron 表达式 启用状态 租户是否释放/设置是否更新共同决定并支持按站点时区换算执行时间。宿主服务ModularBackgroundService框架的托管服务 ModularBackgroundService.cs 周期性完成以下工作Update 阶段遍历运行中的租户从 DI 解析所有IBackgroundTask为每个任务建立/更新调度器读取IBackgroundTaskSettingsProvider持久化设置读取站点时区检测设置变更令牌ChangeTokenRun 阶段对满足CanRun()的任务并行Parallel.ForEachAsync在各自租户作用域内执行task.DoWorkAsync(...)并记录BackgroundTaskState.LastStartTime。执行过程中的关键细节为每个租户创建一个专用的HttpContextShellContextExtensions.cs其中Items[IsBackground] true标识后台执行上下文若站点设置了BaseUrl会用其覆盖 HttpContext 的 Scheme/Host/PathBaseSetBaseUrl保证后台生成的 URL 正确若任务设置了UsePipeline会先BuildPipelineAsync()构建管线再Pipeline.Invoke(httpContext)让 HttpContext 感知端点Endpoint从而支持在后台生成路由 URL——这正是原文档所述是否构建租户路由管线的底层实现。生命周期事件钩子框架同时提供 IBackgroundTaskEventHandler.cs 接口允许在任何任务执行前后挂钩public interface IBackgroundTaskEventHandler { Task ExecutingAsync(BackgroundTaskEventContext context, CancellationToken cancellationToken); Task ExecutedAsync(BackgroundTaskEventContext context, CancellationToken cancellationToken); }执行上下文 BackgroundTaskEventContext.cs 暴露任务名称、租户名、服务提供者以及异常信息任务执行失败后Exception会被填充。宿主服务在执行任务前后会依次调用所有IBackgroundTaskEventHandler的ExecutingAsync/ExecutedAsync并在异常时通过scope.HandleExceptionAsync(ex)统一处理。原子执行与分布式锁为了让后台任务在多实例部署下也不重复执行模块支持原子任务概念当LockTimeout 0 LockExpiration 0时BackgroundTaskSettings.IsAtomic为true。宿主服务在执行任务前会通过 DistributedLockExtensions.TryAcquireBackgroundTaskLockAsync 尝试获取锁if (distributedLock is ILocalLock || !settings.IsAtomic) { return Task.FromResult(ILocker, bool)((null, true)); } return distributedLock.TryAcquireLockAsync( settings.Name _LOCK, TimeSpan.FromMilliseconds(settings.LockTimeout), TimeSpan.FromMilliseconds(settings.LockExpiration));要点锁的键为任务技术名称 _LOCK后缀只有分布式锁IDistributedLock且非ILocalLock且任务为原子任务时才真正加锁本地锁或非原子任务直接放行返回(null, true)获取锁超时则放弃本次执行并记录日志Timeout to acquire a lock on background task ...。这意味着若你的部署只有单个实例或未启用分布式锁功能如 OrchardCore.Redis 的分布式锁Lock 相关配置会被忽略若存在多个前端实例则必须为原子任务配置分布式锁才能保证同一时刻只有一个实例执行该任务。设置持久化与实时生效数据存储任务的运行设置存储在文档数据库YesSql中模型为 BackgroundTaskDocument.cspublic class BackgroundTaskDocument : Document { public Dictionarystring, BackgroundTaskSettings Settings { get; init; } new(StringComparer.OrdinalIgnoreCase); }即一个以任务技术名称为键、BackgroundTaskSettings为值的字典键比较忽略大小写。读写与变更通知BackgroundTaskManager.cs 通过IDocumentManagerBackgroundTaskDocument提供两类读取GetDocumentAsync()读取**不可变缓存**副本供展示与设置提供程序使用LoadDocumentAsync()读取可变副本供更新前修改使用。UpdateAsync/RemoveAsync在写回文档后还会调用_signal.DeferredSignalToken(nameof(BackgroundTaskSettings))发送延迟信号。宿主服务的 Update 阶段监听该变更令牌BackgroundTaskSettingsProvider.ChangeToken一旦检测到变化会将该租户的调度器标记为需要更新使新调度在下个轮询周期立即生效——这就是在管理界面保存设置后任务无需重启即可按新计划运行的实现原理。托管服务配置项后台任务宿主的轮询行为由 BackgroundServiceOptions.cs 控制配置项默认值含义ShellWarmupfalse是否预热预加载所有租户 shell为false时仅对已有管线的租户执行任务PollingTime1 分钟轮询间隔即两次遍历执行租户全部后台任务之间的等待时间MinimumIdleTime10 秒租户后台任务被触发前的最小空闲时间也作为任务之间的最小间隔。这些选项可在宿主应用启动时通过IConfigureOptionsBackgroundServiceOptions调整例如调整轮询频率以加快设置变更的响应速度。小结与最佳实践围绕OrchardCore.BackgroundTasks可以总结出以下实战要点注册即管理实现IBackgroundTask并注册为 DI 服务后任务会自动出现在 Tools → Background Tasks 列表中无需额外编码管理界面声明式默认值用BackgroundTaskAttribute声明标题、描述、默认 cron、锁参数与管线需求管理界面Reset Schedule会恢复这些默认值cron 驱动调度调度完全由 NCrontab 解析的 cron 表达式决定支持站点时区换算修改后通过变更信号实时生效原子任务防重多实例部署时为任务设置LockTimeout/LockExpiration均大于 0并启用分布式锁可保证任务只在一个实例上执行管线用于 URL 生成任务内若需生成路由 URL勾选 Use Tenant Pipeline宿主会先构建并执行租户管线配合站点 BaseUrl 生成正确链接生命周期钩子需要全局监控或拦截任务执行时实现IBackgroundTaskEventHandler的ExecutingAsync/ExecutedAsync。对于在 Orchard Core 中实现定时数据清理、索引同步、邮件批量发送等周期性业务后台任务模块是目前框架提供的最直接、可运维的方案既有框架级的调度与并发控制又有开箱即用的管理界面供站点运维人员随时启停与调参。赞分享CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载相关推荐Salt 调度执行模块 salt.modules.schedule 完全指南管理与运维 minion 定时任务Salt 调度执行模块 salt.modules.schedule 完全指南管理与运维 minion 定时任务 导读 本文围绕 Salt gh_mirror运维配置管理后端Jellyfin Desktop 媒体播放完整指南MPV 驱动的跨平台桌面播放器Jellyfin Desktop 媒体播放完整指南MPV 驱动的跨平台桌面播放器 Jellyfin Desktop 媒体播放客户端把 jellyfin web音视频桌面应用RedwoodJS Background Jobs 后台任务系统完全指南调度、存储与执行RedwoodJS Background Jobs 后台任务系统完全指南调度、存储与执行 本指南基于 RedwoodJS 官方文档 background jo后端前端Web框架开发工具上一篇7个顶级MMEngine调试技巧从卡壳到流畅训练的深度学习开发提速指南下一篇告别缓存一致性难题用Sequin实现PostgreSQL到Redis字符串的实时同步方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考