我们有一个多租户 asp.net mvc(框架,非核心)应用程序,我们在应用程序启动时由租户创建 Hangfire 服务器和队列。当我们有新租户注册或离开时,我们希望添加或删除他们的服务器/队列,而无需重新启动应用程序。有没有办法为.net框架做到这一点?我已经看到这个问题关于如何在.net core中做到这一点。
是的,可以在 ASP.NET MVC(框架)应用程序中动态添加或删除 Hangfire 服务器或队列,而无需重新启动应用程序。你在互联网上找到的大多数方法都是基于 .NET core 的,但 .NET Framework 中也有类似的方法。
要动态管理 Hangfire 服务器和队列,您可以通过控制应用程序中 Hangfire 服务器的生命周期来处理租户添加或删除。
以下是概述:
public class HangfireServerManager
{
private readonly Dictionary<string, BackgroundJobServer> _tenantServers;
public HangfireServerManager()
{
_tenantServers = new Dictionary<string, BackgroundJobServer>();
}
public void AddTenant(string tenantId)
{
if (_tenantServers.ContainsKey(tenantId))
{
throw new InvalidOperationException($"Tenant {tenantId} already has a Hangfire server.");
}
// Configuration for this tenant
var options = new BackgroundJobServerOptions
{
ServerName = $"Server-{tenantId}",
Queues = new[] { tenantId } // Each tenant gets its own queue
};
var server = new BackgroundJobServer(options);
_tenantServers.Add(tenantId, server);
}
public void RemoveTenant(string tenantId)
{
if (!_tenantServers.ContainsKey(tenantId))
{
throw new InvalidOperationException($"Tenant {tenantId} does not have a Hangfire server.");
}
var server = _tenantServers[tenantId];
server.Dispose(); //shut down the server
_tenantServers.Remove(tenantId);
}
public void ShutDownAll()
{
foreach (var server in _tenantServers.Values)
{
server.Dispose();
}
_tenantServers.Clear();
}
}
然后您可以将其挂接到租户入职或离职逻辑中。这可以是 API 端点、计划进程或添加或删除租户时后台作业逻辑的一部分。
public class TenantController : Controller
{
private readonly HangfireServerManager _serverManager;
public TenantController(HangfireServerManager serverManager)
{
_serverManager = serverManager;
}
[HttpPost]
public ActionResult AddTenant(string tenantId)
{
_serverManager.AddTenant(tenantId);
return Ok();
}
[HttpPost]
public ActionResult RemoveTenant(string tenantId)
{
_serverManager.RemoveTenant(tenantId);
return Ok();
}
}
您需要确保每个租户使用正确的 Hangfire 存储(通常是 SQL Server、Redis 等)。如果租户共享相同的存储,则他们的作业队列将通过队列名称来唯一,例如租户特定的队列。
GlobalConfiguration.Configuration
.UseSqlServerStorage("<connection-string>")
.UseFilter(new AutomaticRetryAttribute { Attempts = 3 });
希望这对您有帮助。