How to scale SignalR using Azure Worker Role and OWIN

*爱你&永不变心* 提交于 2019-12-12 14:09:43

问题


SignalR scales fabulously using Azure Web Roles. However, when I use a self-hosted OWIN project inside an Azure Worker Role, SignalR will begin to exhibit problems when multiple instances are added. For the record, my project uses Redis for the backplane.

When increasing the Azure Worker Role instances beyond one, client connections will randomly fail with an error "The ConnectionId is in the incorrect format". I believe this is caused when the negotiation for a single client spans multiple servers due to load-balancing; I do not believe the multiple servers participating in the negotiation can decrypt the data (DPAPI under the covers?).

I tried setting the < machineKey /> validationKey and decryptionKey in app.config but this doesn't appear to make a difference; the problem remains. Again, the project will work fine as a Web Role (IIS), but not a Worker Role (OWIN self-host).

Presuming this is an issue with DpapiDataProtectionProvider, how can I ensure the provider renders the same encrypt/decrypt result across multiple servers/instances?

Solution

The default protection provider used by SignalR (DpapiDataProtectionProvider) does not appear to support Azure Worker Role scaleout. By rolling my own sample provider I was able to scale SignalR/OWIN/Azure Worker and not receive the random 400 HTTP/"The ConnectionId is in the incorrect format". Keep in mind the below sample will not secure/protect the tokens.

public class ExampleDataProvider : IDataProtector
{
    public byte[] Protect(byte[] userData)
    {
        Trace.TraceInformation("Protect called: " + Convert.ToBase64String(userData));
        return userData;
    }

    public byte[] Unprotect(byte[] protectedData)
    {
        Trace.TraceInformation("Unprotect called: " + Convert.ToBase64String(protectedData));
        return protectedData;
    }
}

public class ExampleProtectionProvider : IDataProtectionProvider
{
    public IDataProtector Create(params string[] purposes)
    {
        Trace.TraceInformation("Example Protection Provider Created");
        return new ExampleDataProvider();
    }
}

Injecting the custom provider during Owin startup:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.SetDataProtectionProvider(new ExampleProtectionProvider());

        GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration("0.0.0.0", 0, "", "Example"));

        app.MapSignalR(new HubConfiguration
        {
            EnableDetailedErrors = true
        });

        app.UseWelcomePage("/");
    }
}

回答1:


SignalR uses the IDataProtectionProvider from IAppBuilder.Properties["security.DataProtectionProvider"] if it's not null.

You can replace this with your own IDataProtectionProvider in Startup.Configuration before you call MapSignalR.

By providing you own IDataProtectionProvider, you can ensure that every work role uses the same key to protect/unprotect.



来源:https://stackoverflow.com/questions/22484064/how-to-scale-signalr-using-azure-worker-role-and-owin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!