问题描述
我将多租户构建到一组服务的工作单元中.我想将租约问题放在日常业务领域的工作之外,并且我不想触及系统中的每个现有消费者(我将多租户改造到没有任何租户先验概念的系统上).
系统中的大多数消息将由租户上下文处理.但是,会有一些基础结构消息不会出现,特别是出于自动创建租户的目的.我需要一种确定是使用与租户相关联的工作单元,还是使用与租户无关的基础架构工作单元的方法,因为我与数据库进行交互的方式取决于我是否具有租户上下文.工作单元是在分解消费者的依赖关系的过程中建立的.
因此,在使用消息之前,我需要一种查看消息或其元数据的方法,特别是,我需要能够在依赖项构建期间进行查看.我本来打算使用一个标记接口来将租户管理消息从普通的业务域消息中标记出来,但是任何识别差异的形式都可以使用.如果我属于HTTP请求所导致的工作单元,则可以查看WebApi的HttpContext.Current
并查看当前请求的标头,等等.如果我处于工作单元所导致的结果,该如何做类似的事情来自消息?
我看到有一种方法可以用BeforeConsumingMessage()
截取消息,但是我需要一种将其与我正在旋转的当前工作单元相关联的方法,但是我没有看到它如何对我起作用.我要执行的操作的伪代码:
if MessageContext.Message.GetType() = typeof<ITenantInfrastructureMessage>:
database = new Database(...)
else:
tenantId = MessageContext.Headers.TenantId;
database = new TenantDatabase(..., tenantId)
我正在使用带有RabbitMQ的MassTransit和带有MassTransit的内置支持的Autofac在C#/.NET中工作.
您最好的选择是在IConsumerFactory<T>
扩展点进行覆盖,并从消息中提取租户(通过消息标头或某些消息属性)并将其注册到容器子生存期范围中,以使来自实际使用者类(及其依赖项)的后续解决方案与消息中的租户正确匹配.
在我们的系统中,我们有一个TenantContext,它已在新创建的LifetimeScope(我们正在使用Autofac)中注册,此后,我们从子范围中解析了消耗,并且使用租户上下文的依赖项获得了适当的值.因为它已注册为为消息范围构建子容器的一部分.
它非常好用,我们甚至建立了扩展方法,以使开发人员可以很容易地注册消费者以指定租户上下文提供者",从消息类型到正确的租户ID,用于构建TenantContext. /p>
您可以在Courier路由单(消费者的特殊化)中对活动工厂执行类似的操作.
I building multitenancy into the unit of work for a set of services. I want to keep the tenancy question out of the way of day-to-day business domain work, and I do not want to touch every existing consumer in the system (I am retrofitting the multitenancy onto a system without any prior concept of a tenant).
Most messages in the system will be contexted by a tenant. However, there will be some infrastructure messages which will not be, particularly for the purpose of automating tenant creation. I need a way of determining whether to use a tenant-contexted unit of work, or a infrastructure unit of work uncontexted by a tenant because the way I interact with the database is different depending on whether I have tenant context. The unit of work is built in the process of spinning up the dependencies of the consumer.
As such I need a way of peeking at the message or its metadata before consuming it, and specifically, I need to be able to peek at it during the dependency building. I was intended to have a tag interface to mark tenant management messages out from normal business domain messages, but any form of identifying the difference could work. If I am in a unit of work resulting from an HTTP request, I can look at WebApi's HttpContext.Current
and see the headers of the current request, etc. How do I do something analogous to this if I am in a unit of work resulting from messaging?
I see there is a way to intercept messages with BeforeConsumingMessage()
but I need a way of correlating it to the current unit of work I am spinning up and I'm not seeing how that would work for me. Pseudocode for what I am trying to do:
if MessageContext.Message.GetType() = typeof<ITenantInfrastructureMessage>:
database = new Database(...)
else:
tenantId = MessageContext.Headers.TenantId;
database = new TenantDatabase(..., tenantId)
I am working in C#/.NET using MassTransit with RabbitMQ and Autofac with MassTransit's built-in support for both.
Your best option is to override at the IConsumerFactory<T>
extension point, and extract the tenant from the message (either via a message header, or some message property) and register that in the container child lifetime scope so that subsequent resolutions from the actual consumer class (and it's dependencies) are properly matched to the tenant in the message.
In our systems, we have a TenantContext that is registered in a newly created LifetimeScope (we're using Autofac), after which we resolve the consume from the child scope, and the dependencies that use the tenant context get the proper value since it's registered as part of building the child container for the message scope.
It works extremely well, we even built up extension methods to make it easy for developers registering consumers to specify "tenant context providers" that go from a message type to the proper tenant id, which is used to build the TenantContext.
You can do similar things with activity factories in Courier routing slips (which are a specialization of a consumer).
这篇关于在构建依赖项时如何查看消息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!