gpt4 book ai didi

wcf - 如何清除服务器上的传出消息缓冲区?

转载 作者:行者123 更新时间:2023-12-04 19:05:10 28 4
gpt4 key购买 nike

我已经使用 PollingDuplexHttpBinding 编写了一个服务它有一个使用它的 Silverlllight 客户端。我的服务基本上有给定数量的客户端向服务发送数据(很频繁,每秒,而且数据很大,每次调用大约 5KB),并监听其他客户端发送到服务的新数据路由到它们,非常类似于聊天室架构。

我注意到的问题是,当客户端通过 Internet 连接到服务时,几分钟后服务的响应变慢并且回复变得滞后。我得出的结论是,当服务主机达到上传容量时(互联网上传速度,在服务器上只有大约 15KB/s),其他客户端发送的消息会在有可用带宽时进行缓冲和相应处理。我想知道如何限制服务用来存储从客户端接收到的消息的缓冲区的占用?我的客户获得所有数据并不是那么重要,而是他们获得其他人发送的最新数据,因此实时连接是我以保证交付为代价寻找的东西。

简而言之,我希望能够在服务中的队列/缓冲区填满时清理我的队列/缓冲区,或者达到某个上限,并开始重新填充收到的调用以消除延迟。我该怎么做呢?是MaxBufferSize我需要在服务端和客户端减少什么?或者我需要在我的服务中编码这个功能吗?有任何想法吗?

谢谢。

编辑:

这是我的服务架构:

//the service
[ServiceContract(Namespace = "", CallbackContract = typeof(INewsNotification))]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class NewsService
{


private static Dictionary<IChatNotification, string> clients = new Dictionary<IChatNotification, string>();
private ReaderWriterLockSlim subscribersLock = new ReaderWriterLockSlim();

[OperationContract(IsOneWay = true)]
public void PublishNotifications(byte[] data)
{
try
{
subscribersLock.EnterReadLock();
List<INewsNotification> removeList = new List<INewsNotification>();
lock (clients)
{
foreach (var subscriber in clients)
{
if (OperationContext.Current.GetCallbackChannel<IChatNotification>() == subscriber.Key)
{
continue;
}
try
{
subscriber.Key.BeginOnNotificationSend(data, GetCurrentUser(), onNotifyCompletedNotificationSend, subscriber.Key);

}
catch (CommunicationObjectAbortedException)
{
removeList.Add(subscriber.Key);
}
catch (CommunicationException)
{
removeList.Add(subscriber.Key);
}
catch (ObjectDisposedException)
{
removeList.Add(subscriber.Key);
}

}
}

foreach (var item in removeList)
{
clients.Remove(item);
}
}
finally
{
subscribersLock.ExitReadLock();
}
}

}


//the callback contract
[ServiceContract]
public interface INewsNotification
{
[OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginOnNotificationSend(byte[] data, string username, AsyncCallback callback, object asyncState);
void EndOnNotificationSend(IAsyncResult result);
}

服务配置:
  <system.serviceModel>
<extensions>
<bindingExtensions>
<add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="">

<serviceMetadata httpGetEnabled="true" />
<serviceThrottling maxConcurrentSessions="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<pollingDuplex>

<binding name="myPollingDuplex" duplexMode="SingleMessagePerPoll"
maxOutputDelay="00:00:00" inactivityTimeout="02:00:00"
serverPollTimeout="00:55:00" sendTimeout="02:00:00" openTimeout="02:00:00"
maxBufferSize="10000" maxReceivedMessageSize="10000" maxBufferPoolSize="1000"/>

</pollingDuplex>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="NewsNotificationService.Web.NewsService">
<endpoint address="" binding="pollingDuplex" bindingConfiguration="myPollingDuplex" contract="NewsNotificationService.Web.NewsService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
<system.webServer>
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>

客户端通常会在 500 毫秒到 1000 毫秒之间调用服务,如下所示:
_client.PublishNotificationAsync(byte[] data);
并且回调将通知客户端其他客户端发送的通知:
void client_NotifyNewsReceived(object sender, NewsServiceProxy.OnNewsSendReceivedEventArgs e)
{
e.Usernamer//WHich client published the data
e.data//contents of the notification
}

所以回顾一下,当客户端数量增加,并且服务主机通过互联网上传速度有限时,服务发送给订阅者的消息会在某处缓冲并在队列中处理,这就是导致问题的原因,
我不知道这些消息被缓冲在哪里。在 LAN 中,该服务工作正常,因为服务器的上传速度等于其下载速度(对于 100KB/s 的来电,它发送 100KB/s 的通知)。这些消息在哪里被缓冲?我怎样才能清除这个缓冲区?

我做了一些实验来尝试查看消息是否在服务中缓冲,我尝试在客户端上调用此方法,但它始终返回 0,即使一个客户端仍在接收其他人发送的通知的过程中 4- 5分钟前:
[OperationContract(IsOneWay = false)]
public int GetQueuedMessages()
{

return OperationContext.Current.OutgoingMessageHeaders.Count();
}

最佳答案

我为你的情况做了一些数学计算。

  • 消息大小 = 100KB
  • 上传 channel = 15KB/s
  • 下载 channel = 100KB/s
  • 客户端每秒调用服务 1-2 次

  • client will call the service typically between 500ms-1000ms periods



    这样对吗?

    对于一个客户端,仅用于消息的下载流量将为 100-200KB/s,这只是消息正文。将有更多的标题和更多的启用安全性。

    消息将被合并用于异步调用。因此,如果我们有 3 个客户端,并且每个发送的消息回调包含每个客户端的 2 个消息。 4 个客户端 - 每个回调中有 3 条消息。

    对于 3 个客户端,下载 channel 将是 200-400KB/s。

    对我来说,消息对于您声明的带宽来说似乎太大了。

    检查您是否可以:
  • 减少消息大小。我不了解您的业务性质,因此无法在此提供建议。
  • 对消息或流量使用压缩。
  • 增加网络带宽。没有那个即使是理想的解决方案也会
    有非常高的延迟。您可以花费数天和数周的时间来优化您的
    代码,即使您正确使用了您的网络解决方案
    要慢。

  • 我知道这听起来像船长 Obvious 但有些问题没有正确答案,除非你改变问题。

    使用 ServiceThrottlingBehavior 执行上述步骤后结合将管理回调队列的自定义代码。
    ServiceThrottlingBehavior如果达到边界,则拒绝请求。

    http://msdn.microsoft.com/en-us/library/ms735114(v=vs.100).aspx

    这是微不足道的样本。实数应专门为您的环境定义。
    <serviceThrottling 
    maxConcurrentCalls="1"
    maxConcurrentSessions="1"
    maxConcurrentInstances="1"
    />

    更新:

    Big mistake on my part in the question, each call is 5KB/s,



    即使有 5KB 消息,15KB/s 也是不够的。让我们仅计算 3 个用户的流量。 3 每秒传入消息。系统现在应该使用双工来通知用户其他发送了什么。每个用户都应该从他的合作伙伴那里得到消息。我们总共有 3 条消息。一个(属于发件人)可能会被跳过,所以每个用户都应该收到 2 条消息。 3 个用户将获得 10KB(5KB + 5KB = 一条消息 10KB)= 30KB。
    每秒一条消息将在上传 channel 中为 3 个用户生成 30KB/秒。

    Where are these messages getting buffered? And how can I clear this buffer?



    这取决于您如何托管服务。如果它是自托管服务,则根本不会缓冲。您的代码尝试向接收器发送消息,但由于 channel 被淹没,因此速度非常慢。使用 IIS 可能会有一些缓冲,但从外部接触它不是一个好习惯。

    正确的解决方案是节流。由于带宽限制,您不应尝试将所有消息发送到所有客户端。相反,您应该例如限制发送消息的线程数量。因此,从上面的 3 个用户而不是并行发送 3 条消息,您可以按顺序发送它们,或者决定只有一个用户将在该轮中获得更新,而在下一轮中将获得下一个。

    因此,一般的想法是不要在拥有数据后立即将所有内容发送给所有人,而是仅发送您可以负担得起的数据量,并使用线程数或响应速度进行控制。

    关于wcf - 如何清除服务器上的传出消息缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10931922/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com