[英]ServiceStack.Redis: One thread pool for all MQ request handlers?
[英]ServiceStack.Redis: Configure so that the request and response class/dto is the same class?
不久前我一直在使用 ServiceStack,我很清楚基於消息的 API 設計是首選,這是我在一些基於 REST 的 API 中使用的東西。
我現在正在研究 Redis / MQ 庫,並且一如既往地享受 ServiceStack 的結構和功能。 但是,我正在考慮用 MQ 服務器替換一些遺留通信代碼,並 測試了一些 SS 示例,並且效果很好。
但是,我正在使用的一些遺留代碼使用相同的 class 用於傳出請求和響應,就像發送GetSomething
一樣,並且回復是相同 class GetSomething
的實例,但具有像GetSomething.Result
這樣包含回復的屬性/結果。
由於我想直接替換當前的通信 model,因此我查看了是否可以“開箱即用”支持這種方案,但我並沒有真正找到任何解決這個問題的方法。 當我在具有處理程序的消費者中這樣的事情時:
mqHost.RegisterHandler<GetSomething>(base.ExecuteMessage);
以及想要回復的發布者:
mqServer.RegisterHandler<GetSomething>(m => {...});
發生的情況是發布者立即獲取請求,並且它永遠不會到達消費者。 如果我在 Publisher 中刪除了回復的偵聽器,它會到達消費者,但是當消費者使用相同的 DTO GetSomething
回復時,它會陷入一個永恆的循環,因為我認為回復是放在同一個MQ 隊列。
有沒有使用 ServiceStack 解決這個問題的聰明方法?
我對可能的解決方法有一些想法,但我想知道這是否可以以更好、更智能的方式解決。
我只是想分享一種解決方法,它可能不是最漂亮的,但似乎有效。 如果有更好的方法來做到這一點,我仍然很感興趣。
出版商:
發布者將 RequestFilter 分配給 RedisMqServer,並在該方法中修改.Body
,將包裝器替換為實際請求。
Publisher 然后為響應包裝器 class 調用.RegisterHandler
一次,然后按預期為每個實際/真實 Handler 調用。 這將導致調用正確的服務處理程序:
public RedisClient(string name)
{
Name = name;
redisFactory = new PooledRedisClientManager("localhost:6379");
mqServer = new RedisMqServer(redisFactory, retryCount: 2);
mqServer.RequestFilter = RequestFilter;
// Response wrapper, ContainerResponse implements IProtocolContainer
mqServer.RegisterHandler<ContainerResponse>(m =>
{
return m;
});
mqServer.RegisterHandler<GetSomething>(m =>
{
// m.Body is here an GetSomething
return null;
});
mqServer.Start();
}
private ServiceStack.Messaging.IMessage RequestFilter(ServiceStack.Messaging.IMessage message)
{
if (message.Body is IProtocolContainer protocolContainer)
{
message.Body = protocolContainer.TheRequest;
}
return message;
}
public void AddMessage<T>(T theRequest) where T : CoreRequest
{
using (var mqClient = mqServer.CreateMessageQueueClient())
{
mqClient.Publish(new ContainerRequest(theRequest));
}
}
}
消費者:
同樣的原則也適用於消費者:
public override void Configure(Container container)
{
container.Register(new ConsumerInfo() { Name = ServiceName });
var redisFactory = new PooledRedisClientManager("localhost:6379");
container.Register<IRedisClientsManager>(redisFactory);
var mqHost = new RedisMqServer(redisFactory, retryCount: 2);
mqHost.RequestFilter = RequestFilter;
mqHost.ResponseFilter = ResponseFilter;
mqHost.RegisterHandler<ContainerRequest>(base.ExecuteMessage);
mqHost.RegisterHandler<GetSomething>(base.ExecuteMessage);
mqHost.Start();
}
private object ResponseFilter(object arg)
{
return new ContainerResponse(arg as CoreRequest);
}
private ServiceStack.Messaging.IMessage RequestFilter(ServiceStack.Messaging.IMessage message)
{
if (message.Body is IProtocolContainer protocolContainer)
{
System.Diagnostics.Debug.WriteLine($"\tReplaced Body with {protocolContainer.TheRequest.GetType().Name}");
message.Body = protocolContainer.TheRequest;
}
return message;
}
}
ServiceStack MQ 消息工作流在文檔中定義:
並解釋在以下情況下會發生什么:
因此,返回請求 DTO 會將其放入請求 DTO 的 INQ 中,該請求 DTO 將由注冊處理它的處理程序執行,在這種情況下,它恰好是它自己,因此是循環。 在 Redis MQ 服務返回null
或void
將其發布到 Redis 的瞬態/滾動響應 DTO.outq。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.