问题描述
刚开始了解消息队列和Redis MQ,非常棒框架.
我知道您必须使用 .RegisterHandler(...) 来确定哪个处理程序将处理消息队列中的消息/事件类型.
因此,如果我有 EventA、EventB 等,我应该有一个服务来处理每个事件,例如:
public class DomainService : Service {公共对象 Any(EventA eventA) {...}公共对象 Any(EventB eventA) {...}}
所以这些应该只是创建的队列/redis 列表?
此外,如果我希望发生一系列事件,例如 EventA 类型的消息也有一个处理程序,该处理程序发送电子邮件,提供链上较早的处理程序是否成功?
ServiceStack 没有区分为以下目的创建的服务MQ、REST、HTML 或 SOAP 服务,它们是一回事.即它们每个都接受请求 DTO 并可选择返回响应 DTO,并且相同的服务可以处理来自任何端点或格式的调用,例如 HTML、REST、SOAP 或 MQ.
请参阅ServiceStack 的架构图以了解 MQ 是如何适应的.>
限制
您需要记住的唯一事项是:
- 与 SOAP 一样,MQ 仅支持 1 个动词,因此您的方法需要命名为 Post 或 Any
- 仅执行操作过滤器(即不执行全局或属性过滤器)
- 您可以使用 MqRequest 和 MqResponse 存根代替
IHttpRequest
、IHttpResponse
.您仍然可以使用.Items
通过请求管道传递数据,但任何 HTTP 操作(如设置 cookie 或 HTTP 标头)都是良性的
配置Redis MQ主机
MQ 主机本身与 ServiceStack 框架的其余部分完全分离,直到您自己将消息传递到 ServiceStack 中,谁才知道 MQ 存在,这通常在您注册的处理程序中完成,例如:
var redisFactory = new PooledRedisClientManager("localhost:6379");var mqHost = new RedisMqServer(redisFactory, retryCount:2);mqHost.RegisterHandler(m => {返回 this.ServiceController.ExecuteMessage(m);});//更短的版本://mqHost.RegisterHandler(ServiceController.ExecuteMessage);mqHost.Start();//开始监听消息
在您的 RegisterHandler
中,您指定您希望它侦听的请求类型.
默认情况下,您只能为每条消息注册一个处理程序,并且在 ServiceStack 中,一个请求与已知的服务实现相关联,在 MQ 的情况下,它正在寻找第一个匹配的方法签名:Post(Hello)
,如果它不存在,它会寻找回退 Any(Hello)
.
可以自己为每条消息添加多个处理程序
如果您想调用多个处理程序,那么您只需维护自己的 List
并在请求进入时遍历并执行它们.
调用不同的服务
如果您想调用不同的服务,只需将其转换为不同的请求 DTO 并将其传递给 ServiceController.
当任何人发送 MQ 请求时,例如:
mqClient.Publish(new Hello { Name = "Client" });
您的处理程序使用 IMessage,其中请求 DTO 包含在 Body 属性中.此时,您可以选择丢弃消息、验证它或更改它.
MQ 请求与任何其他服务请求相同
在大多数情况下,您通常会将消息转发到 ServiceController 来处理,其实现为:
公共对象 ExecuteMessage(IMessage mqMsg){返回执行(mqMsg.Body, new MqRequestContext(this.Resolver, mqMsg));}
该实现只是从 mqMsg.Body 中提取请求 DTO,并将该消息作为从那时起传递 C# 请求 DTO 的普通服务进行处理,并使用包含 MQ IHttpRequest 的 MqRequestContext,IHttpResponse 存根.
Just getting my head around message queues and Redis MQ, excellent framework.
I understand that you have to use .RegisterHandler(...) to determine which handler will process the type of message/event that is in the message queue.
So if I have EventA, EventB etc should I have one Service which handles each of those Events, like :
public class DomainService : Service {
public object Any(EventA eventA) {...}
public object Any(EventB eventA) {...}
}
So these should be only queue/redis list created?
Also, what If I want a chain of events to happen, so for example a message of type EventA also has a handler that sends an Email providing handlers earlier on the chain are successful?
ServiceStack has no distinction between services created for MQ's, REST, HTML or SOAP services, they're the same thing. i.e. they each accept a Request DTO and optionally return a Response DTO and the same service can handle calls from any endpoint or format, e.g HTML, REST, SOAP or MQ.
Refer to ServiceStack's Architecture diagram to see how MQ fits in.
Limitations
The only things you need to keep in mind are:
- Like SOAP, MQ's only support 1 Verb so your methods need to be named Post or Any
- Only Action Filters are executed (i.e. not Global or Attribute filters)
- You get MqRequest and MqResponse stubs in place of
IHttpRequest
,IHttpResponse
. You can still use.Items
to pass data through the request pipeline but any HTTP actions like setting cookies or HTTP Headers are benign
Configuring a Redis MQ Host
The MQ Host itself is completely decoupled from the rest of the ServiceStack framework, who doesn't know the MQ exists until you pass the message into ServiceStack yourself, which is commonly done inside your registered handler, e.g:
var redisFactory = new PooledRedisClientManager("localhost:6379");
var mqHost = new RedisMqServer(redisFactory, retryCount:2);
mqHost.RegisterHandler<Hello>(m => {
return this.ServiceController.ExecuteMessage(m);
});
//shorter version:
//mqHost.RegisterHandler<Hello>(ServiceController.ExecuteMessage);
mqHost.Start(); //Starts listening for messages
In your RegisterHandler<T>
you specify the type of Request you want it to listen for.
By default you can only Register a single handler for each message and in ServiceStack a Request is tied to a known Service implementation, in the case of MQ's it's looking for a method signature first matching: Post(Hello)
and if that doesn't exist it looks for the fallback Any(Hello)
.
Can add multiple handlers per message yourself
If you want to invoke multiple handlers then you would just maintain your own List<Handler>
and just go through and execute them all when a request comes in.
Calling different services
If you want to call a different service, just translate it to a different Request DTO and pass that to the ServiceController instead.
When a MQ Request is sent by anyone, e.g:
mqClient.Publish(new Hello { Name = "Client" });
Your handler is invoked with an instance of type IMessage where the Request DTO is contained in the Body property. At that point you can choose to discard the message, validate it or alter it.
MQ Requests are the same as any other Service requests
In most cases you would typically just forward the message on to the ServiceController to process, the implementation of which is:
public object ExecuteMessage<T>(IMessage<T> mqMsg)
{
return Execute(mqMsg.Body, new MqRequestContext(this.Resolver, mqMsg));
}
The implementation just extracts the Request DTO from the mqMsg.Body and processes that message as a normal service being passed a C# Request DTO from that point on, with a MqRequestContext that contains the MQ IHttpRequest, IHttpResponse stubs.
这篇关于如何从我的域中引发的事件在 RedMQ 中设置处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!