servicestack.redis:配置请求和响应类/dto是同一个类?

c9x0cxw0  于 2021-06-09  发布在  Redis
关注(0)|答案(2)|浏览(438)

我很久以前就使用过servicestack,我很清楚基于消息的api设计是首选,这是我在一些基于rest的api中使用的。
我现在正在研究redis/mq库,并一如既往地享受servicestack的结构和功能。不过,我正在研究用mq服务器替换一些遗留通信代码,并测试了一些ss示例,效果很好。
但是,我正在处理的一些遗留代码对传出请求和响应使用相同的类,如 GetSomething 并且回复是同一类的示例 GetSomething ,但拥有像 GetSomething.Result 包含回复/结果的。
因为我想用一个临时替代当前的通信模型,所以我想看看这个场景是否可以“开箱即用”地得到支持,但我并没有找到解决这个问题的方法。当我在具有处理程序的消费者中这样做时:

  1. mqHost.RegisterHandler<GetSomething>(base.ExecuteMessage);

出版商希望得到回复:

  1. mqServer.RegisterHandler<GetSomething>(m => {...});

所发生的情况是,发布者会立即接收请求,而它永远不会到达消费者。如果我删除发布服务器中回复的侦听器,它将到达使用者,但是当使用者使用相同的dto进行回复时, GetSomething ,它陷入了一个永恒的循环中,因为我认为回复被放置在同一个mq队列中。
有没有一种聪明的方法可以使用servicestack来解决这个问题?
我对可能的解决办法有一些想法,但我想知道是否可以用更好更聪明的方法来解决这个问题。

4dbbbstv

4dbbbstv1#

我只想和大家分享一个解决方法,也许不是最漂亮的,但似乎很管用。我仍然有兴趣,如果有更好的方法来做这件事。
出版商:
发布者向redismqserver分配一个requestfilter,并在该方法中修改 .Body ,将 Package 器替换为实际请求。
出版商随后致电 .RegisterHandler 一次用于响应 Package 器类,然后按预期用于每个实际/实际处理程序。这将导致调用正确的服务处理程序:

  1. public RedisClient(string name)
  2. {
  3. Name = name;
  4. redisFactory = new PooledRedisClientManager("localhost:6379");
  5. mqServer = new RedisMqServer(redisFactory, retryCount: 2);
  6. mqServer.RequestFilter = RequestFilter;
  7. // Response wrapper, ContainerResponse implements IProtocolContainer
  8. mqServer.RegisterHandler<ContainerResponse>(m =>
  9. {
  10. return m;
  11. });
  12. mqServer.RegisterHandler<GetSomething>(m =>
  13. {
  14. // m.Body is here an GetSomething
  15. return null;
  16. });
  17. mqServer.Start();
  18. }
  19. private ServiceStack.Messaging.IMessage RequestFilter(ServiceStack.Messaging.IMessage message)
  20. {
  21. if (message.Body is IProtocolContainer protocolContainer)
  22. {
  23. message.Body = protocolContainer.TheRequest;
  24. }
  25. return message;
  26. }
  27. public void AddMessage<T>(T theRequest) where T : CoreRequest
  28. {
  29. using (var mqClient = mqServer.CreateMessageQueueClient())
  30. {
  31. mqClient.Publish(new ContainerRequest(theRequest));
  32. }
  33. }
  34. }

消费者:
同样的原则也适用于消费者:

  1. public override void Configure(Container container)
  2. {
  3. container.Register(new ConsumerInfo() { Name = ServiceName });
  4. var redisFactory = new PooledRedisClientManager("localhost:6379");
  5. container.Register<IRedisClientsManager>(redisFactory);
  6. var mqHost = new RedisMqServer(redisFactory, retryCount: 2);
  7. mqHost.RequestFilter = RequestFilter;
  8. mqHost.ResponseFilter = ResponseFilter;
  9. mqHost.RegisterHandler<ContainerRequest>(base.ExecuteMessage);
  10. mqHost.RegisterHandler<GetSomething>(base.ExecuteMessage);
  11. mqHost.Start();
  12. }
  13. private object ResponseFilter(object arg)
  14. {
  15. return new ContainerResponse(arg as CoreRequest);
  16. }
  17. private ServiceStack.Messaging.IMessage RequestFilter(ServiceStack.Messaging.IMessage message)
  18. {
  19. if (message.Body is IProtocolContainer protocolContainer)
  20. {
  21. System.Diagnostics.Debug.WriteLine($"\tReplaced Body with {protocolContainer.TheRequest.GetType().Name}");
  22. message.Body = protocolContainer.TheRequest;
  23. }
  24. return message;
  25. }
  26. }
展开查看全部
9avjhtql

9avjhtql2#

servicestack mq消息工作流在文档中定义:

并解释了以下情况:

没有响应的邮件将发送到“.outq”主题

带有响应的消息将发布到response.inq

带有replyto的邮件的响应将发布到该地址

带异常的消息将重新尝试,然后发布到.dlq死信队列

因此,返回请求dto将其放入该请求dto的inq中,该请求dto将由注册来处理它的处理程序执行,在本例中,该处理程序恰好是自身,因此是循环。在redis mq服务中返回 null 或者 void 将其发布到redis的 transient /滚动响应dto.outq。

相关问题