SignalR & Autofac - Redis 背板横向扩展

SignalR & Autofac - Redis backplane scaleout

我遇到以下情况:我有一个 SignalR 应用程序,我在其中使用 Autofac 作为依赖项解析器。

public class Startup
{
    public void Configuration(IAppBuilder app)
    { 
        var container = new AutofacContainer().Container;

        var resolver = new AutofacDependencyResolver(container);
        resolver.UseRedis("serverIp", portNumber, "password", "channelName");

        app.UseAutofacMiddleware(container);
        app.MapSignalR(new HubConfiguration
        {
            Resolver = resolver
        });

        resolver.UseRedis("192.168.122.213", 6300, "", "FLEDGG");
        AddSignalRInjection(container, resolver);
    }

    private void AddSignalRInjection(IContainer container,IDependencyResolver resolver)
    {
        var updater = new ContainerBuilder();

        updater.RegisterInstance(resolver.Resolve<IConnectionManager>());
        updater.Update(container);
    }
}

这是 AutofacContainer class.

public class AutofacContainer
{
    public IContainer Container { get; set; }
    public AutofacContainer()
    {
        var builder = new ContainerBuilder();

        builder.RegisterHubs(Assembly.GetExecutingAssembly())
            .PropertiesAutowired();
        builder.RegisterType<Test>()
            .As<ITest>()
            .PropertiesAutowired();

        Container = builder.Build();
    }
}

现在,the official SignalR Redis scaleout documentation from Microsoft 说我应该告诉 GlobalHost.DependencyResolverUseRedis

    public void Configuration(IAppBuilder app)
    {
        // Any connection or hub wire up and configuration should go here
        GlobalHost.DependencyResolver.UseRedis("server", port, "password", "AppName");
        app.MapSignalR();
    }

因为我不再在应用程序中使用GlobalHost(即使我使用GlobalHost Redis 中也绝对没有任何行为)(as the Autofac integration with SignalR and Owin indicates):

A common error in OWIN integration is use of the GlobalHost. In OWIN you create the configuration from scratch. You should not reference GlobalHost anywhere when using the OWIN integration.

由于 Startup class 现在已配置:

var resolver = new AutofacDependencyResolver(container);
resolver.UseRedis("serverIp", portNumber, "password", "channelName");

所以我创建了一个 AutofacDependencyResolver 类型的新 resolver,它成功连接到 Redis PubSub。但问题是,如果我尝试发送一条消息,该消息将重复数千次。

(在 Chrome 控制台中,为了从服务器发送一条消息,我最终陷入了无限循环,客户端收到了无限次)。

所以,问题是:如何在使用 Autofac 作为依赖解析器时设置 SignalR Redis scaleout(注意:在任何情况下我都可以使用另一个依赖解析器)。

谢谢!

编辑:如果您想了解有关解决方案的更多信息,here is the repo 没有此行:

resolver.UseRedis("serverIp", portNumber, "password", "channelName");

谢谢!

编辑:我觉得我应该澄清一些事情:如果我使用 resolver.UseRedis();,每条通常发送(一次)的消息都会发送多次 - 所以如果我订阅 "channelName"在使用 subscribe "channelName" 的 Redis 中,我发现它与客户端的行为一致:每条消息都会发送多次。

接下来要做的是有一个没有 Autofac 的基本 SignalR 应用程序,看看 Redis 的行为如何,虽然我觉得这是一个与 Autofac 相关的问题,更具体地说与配置有关。

谢谢!

更新:显然,在没有 Autofac 的基本 SignalR 应用程序中存在相同的行为。该问题与Autofac无关。

好的,我知道发生了什么事了:

我使用的 Redis 服务器被配置为在一个集群中有多个实例 运行。

默认情况下,如果您有一个 Redis 集群并在任何实例的通道上发布消息,该消息将默认转发到所有其他实例。

In a Redis Cluster clients can subscribe to every node, and can also publish to every other node. The cluster will make sure that published messages are forwarded as needed. The current implementation will simply broadcast each published message to all other nodes.

The Redis cluster specification.

很可能,SignalR 实现被配置为接收来自 Redis 的任何消息,因此我的行为很奇怪。

解决方案是拥有一个不在集群中的 Redis 实例,并且一切正常。

如果您想拥有 SignalR 背板,请不要使用集群中的实例!