Redis ServiceStack:手动调用服务时恢复管道?
作为后续工作,我想了解如何改进手动调用服务。这比我想要的要长,但我觉得背景信息是必要的 执行发布/订阅(广播)时,不使用消息传递API中的正常序列和流,而是在接收到发布/订阅消息时使用IRedisClient、IRedisSubscription获得回调:Redis ServiceStack:手动调用服务时恢复管道?,redis,
servicestack,publish-subscribe,Redis,
servicestack,Publish Subscribe,作为后续工作,我想了解如何改进手动调用服务。这比我想要的要长,但我觉得背景信息是必要的 执行发布/订阅(广播)时,不使用消息传递API中的正常序列和流,而是在接收到发布/订阅消息时使用IRedisClient、IRedisSubscription获得回调: _subscription.OnMessage = (channel, msg) => { onMessageReceived(ParseJsonMsgToPoco(msg)); }; 然后,操作onMessageReceiv
_subscription.OnMessage = (channel, msg) =>
{
onMessageReceived(ParseJsonMsgToPoco(msg));
};
然后,操作onMessageReceived
将依次调用一个正常的.NET/C事件,如下所示:
protected override void OnMessageReceived(MyRequest request)
{
OnMyEvent?.Invoke(this, new RequestEventArgs(request));
}
这是可行的,我得到了我的请求和所有这些,但是,我希望它被简化为另一个流,消息传递API中的流,这意味着,请求会进入服务
类实现,所有正常的样板文件和依赖项注入都会像使用消息传递API一样发生
因此,在我的事件处理程序中,我手动调用服务:
private void Instance_OnMyEvent(object sender, RequestEventArgs e)
{
using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
{
myRequestService.Any(e.Request);
}
}
我看到的效果是,我在container.addScope
中注册的注入依赖项没有作用域,但看起来是静态的。我之所以看到这一点,是因为我在注入的类中有一个Guid,在这种情况下,Guid总是相同的,而每个请求的Guid应该不同
container.AddScoped<IRedisCache, RedisCache>();
container.addScope();
OnBeforeExecute(在服务的子代中)类似于:
public override void onbeforecute(对象requestDto)
{
base.onbeforecute(requestDto);
IRedisCache缓存=TryResolve();
缓存?.SetGuid(Guid.NewGuid());
}
因此,IRedisCache Guid每次都应该不同,但事实并非如此。但是,当我使用消息传递API“从头到尾”时,这一切都很好。似乎如果我在AppHostBase子代中调用TryResolve,AddScope将被忽略,一个实例被放置在容器中,然后再也不会被删除
管道的哪些部分丢失了
未执行以下操作:
myRequestService.Any(e.Request);
物理上只调用MyRequestService
类的Any
C#方法,它不(也不能)做任何其他事情
在服务请求期间调用其他服务的推荐方法是使用
但是,如果要在HTTP请求之外调用服务,则可以在调用完整请求管道时使用来执行不受信任的服务&将HTTP错误响应转换为类型化错误响应:
HostContext.AppHost.RpcGateway.ExecuteAsync()
对于在服务请求之外执行内部/受信任服务,您可以使用ServiceStack MQ,它应用消息请求/响应筛选器、服务操作筛选器和事件
我已向container.addScope注册
不要使用,如果依赖项是线程安全的,则使用Singleton,否则将它们注册为瞬态。如果您需要通过每个请求存储,请在
IRequest.Items中传递它们
谢谢您的回答,我会看看是否可以在您的指导下解决这个问题。我还意识到Any
方法不会做任何事情,但我认为HostContext.ResolveService
可能会起到一些神奇的作用。“不要在HTTP请求之外使用请求范围的依赖项”。在我的例子中,依赖项在AppHostBase子代中注册,并由服务使用(使用消息传递API)。因此,据我所知,我不能真正选择单例,因为有时请求通过消息传递API传入,有时通过发布/订阅传入,如上所述。因此,它是在考虑消息传递API的情况下构建和完成的,我希望将sub/pub方法简化为现有的正确实现。在任何情况下,我将使用您的提示,看看它是如何工作的。谢谢。@Ted所有ResolveService
做的就是从IOC解析一个新的服务实例,并注入IRequest上下文。您只能在AppHost或ConfigureServices()启动类中注册启动时的依赖项,但如果需要在HTTP请求之外执行服务,则不应使用请求范围的依赖项。好的,在正常的消息传递API中,每个请求需要一个实例,因为我们有“跟踪器”(跟踪请求过程中发生的事情),这需要为每个请求创建,因此,AddScope似乎是一种自然的方法。但正如您所解释的,如果您独家使用消息传递API,这是可行的,但如果我们不在请求范围内(它不是一个普通的HTTP API,它是通过/通过Redis的).Transient似乎是错误的,它会在每次访问接口属性时创建新实例?我认为这意味着失去“状态”。嗯。后续操作:使用HostContext.AppHost.ExecuteMessage(theMessage);
在这种情况下对我非常有效;即“钩住”它进入请求管道并使所有DI按预期工作。即使在AppHostBase子代中,在管道的方法中执行时,我也从TryResolve
获得正确的实例,就像在OnAfterExecute
中一样,这对我来说已经足够了!
myRequestService.Any(e.Request);
HostContext.AppHost.RpcGateway.ExecuteAsync()