gpt4 book ai didi

c# - WCF TimeoutException 尽管逐步显示成功返回

转载 作者:可可西里 更新时间:2023-11-01 02:52:01 27 4
gpt4 key购买 nike

我有两个在同一网络上运行的自托管服务。第一个是对 Excel 工作表(或其他来源,但目前这是我用来测试的来源)进行抽样,并将更新发送到订阅的客户端。第二个作为客户端连接到第一个客户端的实例,可选地评估这些输入的一些公式,并以与第一个相同的方式将原始或结果作为更新广播到订阅的客户端。所有这一切都发生在一个 tcp 绑定(bind)上。

当第二个服务尝试同时订阅第一个服务的两个提要时,我的问题就出现了,如果新计算第一次使用两个或多个提要,它就会这样做。我不断收到 TimeoutExceptions,这似乎是在订阅第二个提要时发生的。我在第一台服务器上的调用方法中放置了一个断点并单步执行它,它能够完全完成并返回 true 备份调用堆栈,这表明问题可能是 WCF 的一些烦人的复杂性

第一个服务在端口 8081 上运行,这是被调用的方法:

public virtual bool Subscribe(int fid)
{
try
{
if (fid > -1 && _fieldNames.LeftContains(fid))
{
String sessionID = OperationContext.Current.SessionId;
Action<Object, IUpdate> toSub = MakeSend(OperationContext.Current.GetCallbackChannel<ISubClient>(), sessionID);//Make a callback to the client's callback method to send the updates
if (!_callbackList.ContainsKey(fid))
_callbackList.Add(fid, new Dictionary<String, Action<Object, IUpdate>>());
_callbackList[fid][sessionID] = toSub;//add the callback method to the list of callback methods to call when this feed is updated
String field = GetItem(fid);//get the current stored value of that field
CheckChanged(fid, field);//add or update field, usually returns a bool if the value has changed but also updates the last value reference, used here to ensure there is a value to send
FireOne(toSub, this, MakeUpdate(fid, field));//sends an update so the subscribing service will have a first value
return true;
}
return false;
}
catch (Exception e)
{
Log(e);//report any errors before returning a failure
return false;
}
}

第二个服务在端口 8082 上运行,但在此方法中失败:

public int AddCalculation(string name, string input)
{
try
{
Calculation calc;
try
{
calc = new Calculation(_fieldNames, input, name);//Perform slow creation before locking - better wasted one thread than several blocked ones
}
catch (FormatException e)
{
throw Fault.MakeCalculationFault(e.Message);
}
lock (_calculations)
{
int id = nextID();
foreach (int fid in calc.Dependencies)
{
if (!_calculations.ContainsKey(fid))
{
lock (_fieldTracker)
{
DataRow row = _fieldTracker.Rows.Find(fid);
int uses = (int)(row[Uses]) + 1;//update uses of that feed
try
{
if (uses == 1){//if this is the first use of this field
SubServiceClient service = _services[(int)row[ServiceID]];//get the stored connection (as client) to that service
service.Subscribe((int)row[ServiceField]);//Failing here, but only on second call and not if subscribed to each seperately
}
}
catch (TimeoutException e)
{
Log(e);
throw Fault.MakeOperationFault(FaultType.NoItemFound, "Service could not be found");//can't be caught, if this timed out then outer connection timed out
}
_fieldTracker.Rows.Find(fid)[Uses] = uses;
}
}
}
return id;
}
}
catch (FormatException f)
{
Log(f.Message);
throw Fault.MakeOperationFault(FaultType.InvalidInput, f.Message);
}
}

这些端口可能会改变,但永远不会共享。使用的 tcp 绑定(bind)是在代码中使用以下设置设置的:

_tcpbinding = new NetTcpBinding();
_tcpbinding.PortSharingEnabled = false;
_tcpbinding.Security.Mode = SecurityMode.None;

这是在一个公共(public)库中,以确保它们具有相同的设置,这也是在代码中声明它的原因。

我已经尝试为更多并发调用更改服务节流行为,但没有奏效。它现在被注释掉了,因为它不起作用,但作为引用,这是我尝试过的:

ServiceThrottlingBehavior stb = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 400,
MaxConcurrentSessions = 400,
MaxConcurrentInstances = 400
};
host.Description.Behaviors.RemoveAll<ServiceThrottlingBehavior>();
host.Description.Behaviors.Add(stb);

有没有人遇到过类似的方法工作正常但在发送回调用者时仍然超时的问题?

最佳答案

这是一个难题,据我所知,这是 WCF 的一个复杂问题。它无法处理一个连接在循环中非常快速地被重用。它似乎锁定了套接字连接,尽管尝试添加 GC.Collect() 并没有释放它正在竞争的任何资源。

最后,我发现唯一可行的方法是为每个并发请求创建另一个到同一端点的连接,并在单独的线程上执行它们。可能不是最干净的方式,但它是所有的工作。

可能会派上用场的是我使用 svc 跟踪查看器来监视 WCF 调用以尝试跟踪问题,我从这篇文章中找到了如何使用它:http://www.codeproject.com/Articles/17258/Debugging-WCF-Apps

关于c# - WCF TimeoutException 尽管逐步显示成功返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23362112/

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