Hangfire-多租户,ASP.NET Core-解决正确的租户 [英] Hangfire - Multi tenant, ASP.NET Core - Resolving the correct tenant

查看:273
本文介绍了Hangfire-多租户,ASP.NET Core-解决正确的租户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要使用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 in HangfireContext, so then the TenantCurrentService knows the TenantId retrieved from Hangfire. And from there, our application layer will be able to connect to the right database from our DbContextFactory

    当前状态


    • 当前,我们已经能够使用 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 your TenantCurrentService. 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 as ServerFilterProvider, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆