ServiceStack.Redis:配置为使请求和响应类/ dto是同一类?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ServiceStack.Redis:配置为使请求和响应类/ dto是同一类?相关的知识,希望对你有一定的参考价值。

我已经使用ServiceStack一段时间了,我很了解首选的基于消息的API设计,这是我在一些基于REST的API中使用的东西。

我现在正在研究Redis / MQ库,并且一如既往地享受ServiceStack的结构和功能。但是,我正在研究用MQ服务器替换一些旧的通信代码,并使用tested out some SS examples,并且效果很好。

[但是,我正在使用的一些旧代码使用相同的类来处理传出请求和响应,因此发送了GetSomething,而答复是GetSomething相同类的实例,但是具有类似[ C0],其中包含回复/结果。

由于我想直接替换当前的通信模型,所以我想看看这种情况是否可以“即开即用”地得到支持,但是我并没有真正找到解决该问题的方法。当我在具有Handler的Consumer中这样的事情时:

GetSomething.Result

和想要答复的发布者:

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

发生的情况是,发布者立即收到请求,但从未收到消费者。如果我在发布服务器中删除答复的侦听器,它将到达使用者,但是当使用者随后使用相同的DTO mqServer.RegisterHandler<GetSomething>(m => ...); 进行答复时,它将陷入一个永恒的循环,因为我认为答复放置在相同的位置。 MQ队列。

是否有使用ServiceStack解决此问题的明智方法?

我对可能的解决方法有一些想法,但我想知道是否可以通过更好和更聪明的方式解决。

答案

我只是想分享一个解决方法,它可能不是最漂亮的,但似乎可以解决。我仍然对是否有更好的方法感兴趣。

发布者:

发布者将请求过滤器分配给RedisMqServer,然后用该方法修改GetSomething,用实际请求替换包装器。

然后,发布者为响应包装器类调用一次.Body,然后为预期的每个实际/实际Handler调用.RegisterHandler。这将导致调用正确的服务处理程序:

    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 Message Workflow在文档中定义:

ServiceStack MQ Message Workflow

并说明何时会发生什么:

Messages with no responses are sent to ‘.outq’ Topic

Messages with Responses are published to the Response .inq

因此,返回请求DTO会将其放入该请求DTO的INQ中,该请求DTO将由为处理该请求而注册的处理程序执行,在这种情况下恰好是它本身,因此是循环。在Redis MQ Services中,返回nullvoid将其发布到Redis的瞬态/滚动响应DTO .outq。

以上是关于ServiceStack.Redis:配置为使请求和响应类/ dto是同一类?的主要内容,如果未能解决你的问题,请参考以下文章

ServiceStack.Redis 请求次数6000次异常

ServiceStack.Redis:PooledRedisClientManager和RedisManagerPool等待上一请求完成

VS 2008上的ServiceStack.redis配置

关于ServiceStack.Redis的一些问题

使用Redis的基本操作

哪个 Canoe 版本与链接中为 REDIS 客户端实现提供的 soln 兼容 https://github.com/ServiceStack/ServiceStack.Redis