从.NET 1.1迁移到3.5后出现意外行为

时间:2011-08-05 08:19:32

标签: c# .net multithreading web-services service

在工作中,我们最近将一组服务从框架1.1迁移到框架3.5。我们刚刚导入并重新编译了旧的(1.1)项目。

那些服务每7秒检查一次DB,为每个任务创建一个线程(使用ThreadPool)创建一个同步(在线程范围内)Web服务调用(以及其他一些东西)。调用完成后,线程就完成了。

我们只有在ThreadPool获得至少50%的可用线程总数时才创建一个新线程(我们使用ThreadPool.GetAvailableThreads来检查)。如果是,则创建线程,否则服务等待一秒钟(Thread.Sleep(1000);),然后进行新的检查。

所有这些在1.1中工作正常,但似乎在3.5中工作正常,但仅限于测试机器。

所有问题一旦发布到生产机器就开始了:检查和线程正确完成,但Web服务调用启动时有很大的延迟(甚至20分钟以上)并且缓慢解决:1.1版本完成3调用每秒(或多或少),3.5版本每20秒解析一次呼叫(如上所述,每个呼叫延迟20分钟)。我们没有看到任何连接问题,也没有超时。

我们看到的是,当我们启动服务时,在很短的时间内分配了一些线程(大约30个),并且每个线程立即开始一个WS调用(即代码执行。()同步调用)。问题是这些调用只能在一次调用后几分钟解决。

现在:为什么这只发生在生产机器上?为什么在其他测试机上不会发生这种情况?

有什么建议吗?

提前致谢。

修改

我们对服务进行了一些更改。现在我们最多允许在线程池中分配固定数量的线程(35)。达到此数量后,服务将等待线程在创建新线程之前完成。这个过程很好,但我们仍然注意到每个Web请求都在更长的时间内执行:

[11:48:40,365] [  336] INFO  MyClass.Call(): Time elapsed: 00:04:07.0172059
[11:49:14,771] [ 3052] INFO  MyClass.Call(): Time elapsed: 00:04:41.4236761
[11:49:27,256] [ 3928] INFO  MyClass.Call(): Time elapsed: 00:04:53.9081310
[11:49:51,303] [ 5444] INFO  MyClass.Call(): Time elapsed: 00:05:17.9551599
[11:50:34,787] [ 5332] INFO  MyClass.Call(): Time elapsed: 00:06:00.2054303
[11:50:55,366] [ 4672] INFO  MyClass.Call(): Time elapsed: 00:06:19.7211802
[11:51:15,288] [ 1248] INFO  MyClass.Call(): Time elapsed: 00:06:38.6588014
[11:51:34,975] [ 4168] INFO  MyClass.Call(): Time elapsed: 00:06:57.3307959
[11:53:00,429] [ 5224] INFO  MyClass.Call(): Time elapsed: 00:08:18.7531920
[11:53:18,367] [  908] INFO  MyClass.Call(): Time elapsed: 00:08:35.7064255
[11:53:44,398] [ 3616] INFO  MyClass.Call(): Time elapsed: 00:09:00.7222106
[11:54:04,523] [ 6108] INFO  MyClass.Call(): Time elapsed: 00:09:19.8942083
[11:54:29,523] [ 5536] INFO  MyClass.Call(): Time elapsed: 00:09:43.8943619
[11:54:47,242] [ 5048] INFO  MyClass.Call(): Time elapsed: 00:10:00.5819687
[11:55:05,992] [ 3756] INFO  MyClass.Call(): Time elapsed: 00:10:18.3164572
[11:55:26,508] [ 4628] INFO  MyClass.Call(): Time elapsed: 00:10:37.8322071
[11:55:52,493] [ 5812] INFO  MyClass.Call(): Time elapsed: 00:11:02.8167420
[11:56:22,305] [ 5752] INFO  MyClass.Call(): Time elapsed: 00:11:32.0356790
[11:56:31,680] [ 4688] INFO  MyClass.Call(): Time elapsed: 00:11:41.0513617
[11:57:00,556] [ 5844] INFO  MyClass.Call(): Time elapsed: 00:12:08.8952899
[11:57:10,759] [ 5760] INFO  MyClass.Call(): Time elapsed: 00:12:18.0203483
[11:57:49,321] [ 5684] INFO  MyClass.Call(): Time elapsed: 00:12:35.3017089
[11:57:59,056] [ 5920] INFO  MyClass.Call(): Time elapsed: 00:12:26.9110302

进一步检查证明有效的TCP呼叫在大约20秒内持续,但仅在代码呼叫后几分钟执行。

例如,以下代码:

slg.Info("Beginning connection.");

DateTime callStart = DateTime.Now;

odOutput = ws_Proxy.WSMethod(odInput);;

log.InfoFormat("Time elapsed: {0}", DateTime.Now - callStart);

生成此日志

[11:47:59,396] [ 5468] INFO  MyClass.Call(): Beginning connection.
[12:00:17,026] [ 5468] INFO  MyClass.Call(): Time elapsed: 00:12:17.6297208

但TCP连接仅在11:59:56,039进行,并在12:00:17,404完成

11:59:56.0399905 TCP Connect    SUCCESS Length: 0, mss: 1300, sackopt: 4, tsopt: 0, wsopt: 0, rcvwin: 64240, rcvwinscale: 0, sndwinscale: 0, connid: 2254643208, seqnum: 155953480  0
11:59:56.8962917 TCP Send...    SUCCESS Length: 302, startime: 1012803, endtime: 1012811, connid: 2254643208, seqnum: 0 0
11:59:56.9794909 TCP Receive    SUCCESS Length: 2, connid: 2254643208, seqnum: 0    0
11:59:57.7751084 TCP Send...    SUCCESS Length: 625, startime: 1012806, endtime: 1012820, connid: 2254643208, seqnum: 0 0
11:59:57.7751656 TCP Receive    SUCCESS Length: 2, connid: 2254643208, seqnum: 0    0
12:00:08.3723058 TCP Receive    SUCCESS Length: 1300, connid: 2254643208, seqnum: 0 0
12:00:16.5336435 TCP Unknown    SUCCESS Length: 0, connid: 2254643208, seqnum: 0    0
12:00:16.5337723 TCP Receive    SUCCESS Length: 1265, connid: 2254643208, seqnum: 0 0
12:00:17.4046865 TCP Disconnect SUCCESS Length: 0, connid: 2158355531, seqnum: 4133859281   0

在11:47:59,396和11:59:56,039之间发生了什么?为什么呼叫和实际连接之间的间隔增长如此之大?为什么只有在异步执行大量请求时才会发生此行为?这就像框架一次无法执行多个连接......

2 个答案:

答案 0 :(得分:2)

a)ThreadPool的算法和限制已经改变。你使用AvailableThreads / 2的方法可能只运行一次,但在我的Win7笔记本电脑上,1023/2和500线程太多了。

b)您正在查看Threads和ThreadPool,但从您的描述中它也可能是网络或防火墙问题。

答案 1 :(得分:0)

最后我们发现了一个似乎是由代理引起的问题(系统管理员无法告诉谁或为什么配置这个代理)。

此代理仅由作为系统运行的进程(如服务)激活。以用户身份运行的进程(如用于测试的小应用程序)不使用此代理,这就是为什么小型测试应用程序在服务运行时运行时会出现一些问题。

我们解决了这个问题,只需在服务配置中添加以下行:

<system.net>
  <defaultProxy enabled="false" />
</system.net>