我用: SqlScaleoutConfiguration中的SignalR 2.2.2 Rebus 3.0.1
存储在Rebus中的某些事件由通知中心处理,并使用signalR推送到客户端。
一切正常,但今天早上,在发布新版本后,没有一个客户收到“新版本”消息,可能是因为以下异常:
#include "Box.h"
int main() {
Box b(42);
Box2 b2;
b2.PrintBox(b);
return 0;
}
Rebus队列中的消息结果正确处理。
处理程序是这样的:
10:39:04.586| |ERROR| |ProcessId=8196| |ThreadId=5| |SignalR.SqlMessageBus| |Stream 0 : Error starting SQL notification listener: System.Runtime.Serialization.SerializationException: Type 'Rebus.Transport.TransactionContext' in Assembly 'Rebus, Version=3.0.1.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Server stack trace:
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList argsToSerialize)
at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage..ctor(IMethodCallMessage mcm)
at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.SmuggleIfPossible(IMessage msg)
at System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(IMessage reqMsg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at System._AppDomain.CreateInstance(String assemblyName, String typeName)
at System.Data.SqlClient.SqlDependency.CreateProcessDispatcher(_AppDomain masterDomain)
at System.Data.SqlClient.SqlDependency.ObtainProcessDispatcher()
at System.Data.SqlClient.SqlDependency.Start(String connectionString, String queue, Boolean useDefaults)
at Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.StartSqlDependencyListener()
它通过重启解决了,但我需要了解发生了什么。
我类似的问题是:
但我认为情况并非如此。
答案 0 :(得分:1)
除了你已经发现的内容之外,我很难告诉你这里发生了什么:SignalR 出于某些奇怪的原因似乎想要序列化当前执行上下文中隐藏的值,并且其中一个值是Rebus目前的交易背景。
正如您所包含的链接中所述,Rebus在处理消息时以这种方式存储“环境事务”,允许所有自己的操作在同一工作单元中登记。
你可以使用here解释的方法,其中以这样安全的方式临时删除交易上下文
public async Task Handle(SomeMessage message)
{
var transactionContext = AmbientTransactionContext.Current;
AmbientTransactionContext.Current = null;
try
{
JuggleWithAppDomainsInHere();
}
finally
{
AmbientTransactionContext.Current = transactionContext;
}
}
可能会在实现Dispose
的类中将相关位分别移动到构造函数/ IDisposable
方法,从而使API更加平滑:
using(new DismantleAmbientRebusStuff())
{
JuggleWithAppDomainsInHere();
}
我认为,如果我们想知道究竟发生了什么,那么对SignalR有很多了解的人就需要插手。
答案 1 :(得分:0)
我忘记了这个问题,但是稍后我通过解决方法解决了这个问题。
线索是SqlMessageBus在初始化上下文时会对其进行序列化,并且这是在第一次调用GetHubContext进行检索时发生的,因此我在执行任何命令之前强制对其进行了初始化。
app.MapSignalR();
var context = new OwinContext(app.Properties);
var token = context.Get<CancellationToken>("host.OnAppDisposing");
if (token != CancellationToken.None)
{
token.Register(() =>
{
log.Info("host.OnAppDisposing");
// code to run when server shuts down
BackendMessageBusConfig.DisposeContainers();
});
}
// this code brings forward SignalR SqlMessageBus initialization
var forceInit = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
BackendMessageBusConfig.Register();