如何使用 Azure 辅助角色和 OWIN 缩放 SignalR [英] How to scale SignalR using Azure Worker Role and OWIN
问题描述
SignalR 使用 Azure Web 角色进行了惊人的扩展.但是,当我在 Azure 辅助角色中使用自托管 OWIN 项目时,添加多个实例时 SignalR 将开始出现问题.作为记录,我的项目使用 Redis 作为背板.
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.
当 Azure Worker Role 实例数超过 1 时,客户端连接将随机失败并显示错误ConnectionId 的格式不正确".我相信这是由于负载平衡导致单个客户端的协商跨越多个服务器时引起的;我不相信参与协商的多个服务器可以解密数据(幕后的 DPAPI?).
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?).
我尝试设置 <machineKey/> 验证密钥和解密密钥在 app.config 但这似乎没有什么区别;问题依然存在.同样,该项目可以作为 Web 角色 (IIS) 正常工作,但不能作为工作角色(OWIN 自托管).
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).
假设这是 DpapiDataProtectionProvider 的问题,我如何确保提供程序在多个服务器/实例之间呈现相同的加密/解密结果?
Presuming this is an issue with DpapiDataProtectionProvider, how can I ensure the provider renders the same encrypt/decrypt result across multiple servers/instances?
解决方案
SignalR 使用的默认保护提供程序 (DpapiDataProtectionProvider) 似乎不支持 Azure 辅助角色扩展.通过滚动我自己的示例提供程序,我能够扩展 SignalR/OWIN/Azure Worker 并且不会收到随机的 400 HTTP/ConnectionId 的格式不正确".请记住,以下示例不会保护/保护令牌.
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();
}
}
在 Owin 启动期间注入自定义提供程序:
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("/");
}
}
推荐答案
SignalR 使用 IAppBuilder.Properties["security.DataProtectionProvider"] 中的 IDataProtectionProvider,如果它不为空.
SignalR uses the IDataProtectionProvider from IAppBuilder.Properties["security.DataProtectionProvider"] if it's not null.
在调用 MapSignalR 之前,您可以在 Startup.Configuration 中将其替换为您自己的 IDataProtectionProvider.
You can replace this with your own IDataProtectionProvider in Startup.Configuration before you call MapSignalR.
通过提供您自己的 IDataProtectionProvider,您可以确保每个工作角色使用相同的密钥来保护/取消保护.
By providing you own IDataProtectionProvider, you can ensure that every work role uses the same key to protect/unprotect.
这篇关于如何使用 Azure 辅助角色和 OWIN 缩放 SignalR的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!