Hangfire-多租户,ASP.NET Core-解决正确的租户 [英] Hangfire - Multi tenant, ASP.NET Core - Resolving the correct tenant
问题描述
我有一个需要使用Hangfire的SaaS项目。我们已经实施了确定租户的要求。
I got a SaaS project that needs the use Hangfire. We already implemented the requirements to identify a tenant.
建筑
- 持久层
- 每个租户都有自己的数据库
- 我们已经有一个服务
TenantCurrentService
,该服务可返回租户,从来源[主机名,查询字符串等]列表中 - 我们已经有一个用于实体框架的
DbContextFactory
,该实体返回具有客户端正确连接字符串的数据库上下文 - 我们当前正在使用ASP.NET Core DI(如果有帮助,我们会进行更改)
- We already have a service
TenantCurrentService
which returns the ID of the tenant, from a list of source [hostname, query string, etc] - We already have a
DbContextFactory
for Entity Framework which return a DB context with the correct connection string for the client - We are currently using ASP.NET Core DI (willing to change if that helps)
- 使用单一存储(例如:Postgresql),无论租户数如何
- 在适当的Container / ServiceCollection中执行作业,因此我们检索正确的数据库,正确的设置等。
概率lem
我正在尝试将TenantId标记到作业,该作业是从
TenantCurrentService
(其中是一个范围服务)。I'm trying to stamp a TenantId to a job, retrieved from
TenantCurrentService
(which is a Scoped service).然后执行作业时,我们需要从作业中检索
TenantId
并将其存储在HangfireContext
中,因此TenantCurrentService
知道从Hangfire中检索到的TenantId。从那里,我们的应用程序层将能够从我们的DbContextFactory
When the job then gets executed, we need to retrieve the
TenantId
from the Job and store it inHangfireContext
, so then theTenantCurrentService
knows the TenantId retrieved from Hangfire. And from there, our application layer will be able to connect to the right database from ourDbContextFactory
当前状态
- 当前,我们已经能够使用
IClientFilter存储从服务中检索到的tenantId
。 - 如何从IServerFilter检索当前的ASP.NET Core DI ServiceScope(负责检索保存的Job参数),因此可以调用。 GetRequiredService()。IdentifyTenant(tenantId)
关于此事是否有任何好的文章/或者你们可以提供任何提示?
Is there any good article regarding this matter / or any tips that you guys can provide?
推荐答案
首先,您需要能够在自己的计算机中设置
TenantId
TenantCurrentService
。
然后,您可以依靠过滤器:First, you need to be able to set the
TenantId
in yourTenantCurrentService
. Then, you can rely on filters :客户端(在此处排队工作)
client side (where you enqueue jobs)
public class ClientTenantFilter : IClientFilter { public void OnCreating(CreatingContext filterContext) { if (filterContext == null) throw new ArgumentNullException(nameof(filterContext)); filterContext.SetJobParameter("TenantId", TenantCurrentService.TenantId); } }
和服务器端(作业已出队)。
and server side (where the job is dequeued).
public class ServerTenantFilter : IServerFilter { public void OnPerforming(PerformingContext filterContext) { if (filterContext == null) throw new ArgumentNullException(nameof(filterContext)); var tenantId = filterContext.GetJobParameter<string>("TenantId"); TenantCurrentService.TenantId = tenantId; } }
在配置服务器时可以声明服务器过滤器通过
IJobFilterProvider
:The server filter can be declared when you configure your server through an
IJobFilterProvider
:var options = new BackgroundJobServerOptions { Queues = ..., FilterProvider = new ServerFilterProvider() }; app.UseHangfireServer(storage, options, ...);
其中ServerFilterProvider为:
where ServerFilterProvider is :
public class ServerFilterProvider : IJobFilterProvider { public IEnumerable<JobFilter> GetFilters(Job job) { return new JobFilter[] { new JobFilter(new CaptureCultureAttribute(), JobFilterScope.Global, null), new JobFilter(new ServerTenantFilter (), JobFilterScope.Global, null), }; } }
实例化BackgroundJobClient时可以声明客户端过滤器
The client filter can be declared when you instantiate a BackgroundJobClient
var client = new BackgroundJobClient(storage, new BackgroundJobFactory(new ClientFilterProvider());
其中
ClientFilterProvider
的行为与ServerFilterProvider
,提供客户端过滤器where
ClientFilterProvider
behaves asServerFilterProvider
, delivering client filter一个困难之处可能是可以在过滤器中使用TenantCurrentService,我想应该可以通过在FilterProviders中注入工厂并将其链接到
A difficulty may be to have the TenantCurrentService available in the filters. I guess this should be achievable by injecting factories in the FilterProviders and chain it to the filters.
我希望这会有所帮助。
这篇关于Hangfire-多租户,ASP.NET Core-解决正确的租户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!