WCF发布/订阅:如何处理客户端超时以避免丢失信息?

WCF发布/订阅:如何处理客户端超时以避免丢失信息?,wcf,timeout,publish-subscribe,reconnect,Wcf,Timeout,Publish Subscribe,Reconnect,我有一个简单的WCF发布/订阅并正在运行。我正在使用启用了reliableSession的netTcpBinding。所有功能都可以正常工作(订阅的客户端按预期接收已发布的数据),但如果连接闲置一段时间,则在某个时候连接会超时。我可以设置发布服务器在超时时重新连接,但订阅的客户端将丢失。有办法让他们回来吗?我不希望只是增加超时,因为这可能会导致其他问题。我最终提出的解决方案是为每个已发布的消息分配一个唯一标识符,并将已发布的消息缓存在服务适配器中(与我存储对已订阅客户端的回调的位置相同。每当我发

我有一个简单的WCF发布/订阅并正在运行。我正在使用启用了reliableSession的netTcpBinding。所有功能都可以正常工作(订阅的客户端按预期接收已发布的数据),但如果连接闲置一段时间,则在某个时候连接会超时。我可以设置发布服务器在超时时重新连接,但订阅的客户端将丢失。有办法让他们回来吗?我不希望只是增加超时,因为这可能会导致其他问题。

我最终提出的解决方案是为每个已发布的消息分配一个唯一标识符,并将已发布的消息缓存在服务适配器中(与我存储对已订阅客户端的回调的位置相同。每当我发布消息时,订阅者将收到消息和相应的唯一id。然后订阅者可以使用channel.Faulted event重新连接并使用一种特殊方法重新订阅服务,该方法使用最后收到的消息消息id作为参数

服务代码:

    /// <summary>
    /// Operation used by the subscriber to subscribe to events published.
    /// </summary>
    public void Resubscribe(int lastReceivedMessageId)
    {
        // Get callback contract
        IPubSubCallback callback = OperationContext.Current.GetCallbackChannel<IPubSubCallback>();
        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            adapter.Resubscribe(lastReceivedMessageId, callback);
        }); 
    }
//
///订阅服务器用于订阅已发布事件的操作。
/// 
public void重新订阅(int lastReceivedMessageId)
{
//获取回调合同
IPubSubCallback callback=OperationContext.Current.GetCallbackChannel();
ThreadPool.QueueUserWorkItem(委托(对象状态)
{
重新订阅(lastReceivedMessageId,回调);
}); 
}
适配器代码:

/// <summary>
    /// Operation used by the subscriber to resubscribe to events published.
    /// </summary>
    public void Resubscribe(int lastReceivedMessageId, IPubSubCallback callback)
    {
        try
        {
            // Send the subscriber any missed messages
            foreach (KeyValuePair<int, string> missedMessage in publishedMessages.Where(x => x.Key > lastReceivedMessageId))
            {
                callback.MessagePublished(missedMessage.Value, missedMessage.Key);
            }

            // Add the subscriber callback to the list of active subscribers
            if (!callbacks.Contains(callback))
            {
                callbacks.Add(callback);
            }
        }
        catch
        {
            // ignore subscription, callbacks failed again
        }
    }
//
///订阅服务器用于重新订阅已发布事件的操作。
/// 
public void重新订阅(int lastReceivedMessageId,IPubSubCallback回调)
{
尝试
{
//向订户发送任何丢失的消息
foreach(publishedMessages.Where(x=>x.Key>lastReceivedMessageId)中的KeyValuePair missedMessage)
{
MessagePublished(missedMessage.Value,missedMessage.Key);
}
//将订阅服务器回调添加到活动订阅服务器列表中
如果(!callbacks.Contains(callback))
{
callbacks.Add(callback);
}
}
抓住
{
//忽略订阅,回调再次失败
}
}
然后,服务可以计算出客户端遗漏了什么,并按照正确的顺序重新发送这些消息


这个解决方案对我来说似乎很有效,但我觉得一定有更好的方法可以做到这一点。欢迎评论/其他答案!:)

我最终提出的解决方案是为发布的每条消息分配一个唯一标识符,并将发布的消息缓存在服务适配器中(与我存储对已订阅客户端的回调的位置相同。每当我发布消息时,订阅者将收到消息和相应的唯一id。然后订阅者可以使用channel.Faulted event重新连接并使用一种特殊方法重新订阅服务,该方法使用最后收到的消息消息id作为参数

服务代码:

    /// <summary>
    /// Operation used by the subscriber to subscribe to events published.
    /// </summary>
    public void Resubscribe(int lastReceivedMessageId)
    {
        // Get callback contract
        IPubSubCallback callback = OperationContext.Current.GetCallbackChannel<IPubSubCallback>();
        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            adapter.Resubscribe(lastReceivedMessageId, callback);
        }); 
    }
//
///订阅服务器用于订阅已发布事件的操作。
/// 
public void重新订阅(int lastReceivedMessageId)
{
//获取回调合同
IPubSubCallback callback=OperationContext.Current.GetCallbackChannel();
ThreadPool.QueueUserWorkItem(委托(对象状态)
{
重新订阅(lastReceivedMessageId,回调);
}); 
}
适配器代码:

/// <summary>
    /// Operation used by the subscriber to resubscribe to events published.
    /// </summary>
    public void Resubscribe(int lastReceivedMessageId, IPubSubCallback callback)
    {
        try
        {
            // Send the subscriber any missed messages
            foreach (KeyValuePair<int, string> missedMessage in publishedMessages.Where(x => x.Key > lastReceivedMessageId))
            {
                callback.MessagePublished(missedMessage.Value, missedMessage.Key);
            }

            // Add the subscriber callback to the list of active subscribers
            if (!callbacks.Contains(callback))
            {
                callbacks.Add(callback);
            }
        }
        catch
        {
            // ignore subscription, callbacks failed again
        }
    }
//
///订阅服务器用于重新订阅已发布事件的操作。
/// 
public void重新订阅(int lastReceivedMessageId,IPubSubCallback回调)
{
尝试
{
//向订户发送任何丢失的消息
foreach(publishedMessages.Where(x=>x.Key>lastReceivedMessageId)中的KeyValuePair missedMessage)
{
MessagePublished(missedMessage.Value,missedMessage.Key);
}
//将订阅服务器回调添加到活动订阅服务器列表中
如果(!callbacks.Contains(callback))
{
callbacks.Add(callback);
}
}
抓住
{
//忽略订阅,回调再次失败
}
}
然后,服务可以计算出客户端遗漏了什么,并按照正确的顺序重新发送这些消息


这个解决方案对我来说似乎效果不错,但我觉得一定有更好的方法可以做到这一点。欢迎评论/其他答案!:)

如果“客户端”不是最终用户机器,而是数量有限的服务器,你可以尝试使用WCF。它“更好”从某种意义上说,消息保证以异步方式传递。缺点是,只有在设置和配置是自动化的情况下,才能在每台计算机上配置MSMQ。谢谢!这种方法可能对我未来的一些发布-订阅需求有用。我将研究如何设置:)如果“客户端”不是终端用户机器,而是数量有限的服务器,您可以尝试使用WCF。它“更好”从某种意义上说,消息保证以异步方式传递。不利的一面是,只有在自动设置和配置的情况下,才能在每台计算机上配置MSMQ。谢谢!这种方法可能对我未来的一些发布-订阅需求有用。我将研究如何设置:)