Code

 

这是Asp.net中的异步处理。Asp.net的异步处理目的就是要搞高服务器的接受请求的处理能力,但有一点不明白

使用异步处理时,在BeginProcessRequest时,会将处理当前请求的线程放回到线程池中。放回到线程池中的此

线程继续接受新的请求,但是在StartAsyncWork这个时候,同样会从当前线程池中获取一个线程继续处理这个IO,

这样并不能提高服务器的吞吐量,相反会在线程间切换浪费CPU时间和资源,Asp.net异步处理就没有意义了

(其实是有意义的)。

问题:Asp.net的异步能够提高服务器的吞吐量,

 

但是我始终无法理解他是怎么提高其处理能力的。

Posted on 2008-11-22 15:50 rosanshao 阅读(2858) 评论(23)  编辑 收藏 网摘 Body:203.125,BeforeCate:78.125,15.625

Feedback

#1楼   回复  引用  查看    

2008-11-21 12:27 by 刘守照      
thread分为工作者线程和IO线程把
所以应该让IO线程等待,不会长时间block worker thread,
能够提高throughput

#2楼   回复  引用  查看    

2008-11-21 12:38 by montaque      
简单讲

异步就是发 Email 请人家办事
同步就是打电话

想想你是办事的人,发Email 处理的case多,还是接电话处理的case多

case 多事一个因素

质量呢?

#3楼[楼主]   回复  引用  查看    

2008-11-21 12:38 by rosanshao      
To montaque 嗯,但是 ThreadPool.QueueUserWorkItem这样使用也无法确定从线程池中取回的线程就是IO线程。

#4楼[楼主]   回复  引用  查看    

2008-11-21 12:43 by rosanshao      
--引用--------------------------------------------------
montaque: 简单讲

异步就是发 Email 请人家办事
同步就是打电话

想想你是办事的人,发Email 处理的case多,还是接电话处理的case多

case 多事一个因素

质量呢?

--------------------------------------------------------
不明白是什么意思?

#5楼   回复  引用  查看    

2008-11-21 12:49 by eclipse-ms      
异步其实也不错的啊!异步处理数据,就事倍功半了!

#6楼   回复  引用  查看    

2008-11-21 13:04 by Cheese      
我的理解是:这样的异步模型,你可以在BeginProcessRequest的时候,给用户一个友好的界面,告诉他系统正在处理他的请求,而使用同步的方式,请求完全被阻塞,浏览器一直在等待或者处于假死状态,用户的请求将得不到任何反馈。

#7楼   回复  引用    

2008-11-21 13:08 by 静静的黎明tm[未注册用户]
我觉得,其实这个吞吐量就是并发量.

如果原来都是一个线程来完成整个用户请求的始末。

现在就是象一个生产者消费者的关系模型。 也是一个队列的模型

生产者就是接受用户的请求,然后他只负责将任务入队到消费者线程池等待的队列中,

实际的工作量没有变, 但不会因为前台的高并发,导致生产者忙碌。

#8楼[楼主]   回复  引用  查看    

2008-11-21 13:10 by rosanshao      
--引用--------------------------------------------------
Cheese: 我的理解是:这样的异步模型,你可以在BeginProcessRequest的时候,给用户一个友好的界面,告诉他系统正在处理他的请求,而使用同步的方式,请求完全被阻塞,浏览器一直在等待或者处于假死状态,用户的请求将得不到任何反馈。
--------------------------------------------------------
这个异步处理全部是在服务器端,没有仍然客户端的东西。如果你要想浏览器不处于等待或者处于假死状态,那么你可以使用Ajax的异步。

这个是服务器端的异步处理,Asp.net的异步处理的目的就是提高服务器的吞吐量

#9楼   回复  引用  查看    

2008-11-21 15:22 by Cheese      
多谢楼主的提醒,那是否可以这样理解:
不是所有的请求都需要5秒的处理时间,有些请求可能很快就完成了,这个异步就是为了不阻塞那些很快完成的请求,这样一来吞吐量就提高了。

#10楼   回复  引用  查看    

2008-11-21 16:21 by GUO Xingwang      
@静静的黎明tm
比较同意这种看法

#11楼[楼主]   回复  引用  查看    

2008-11-21 16:53 by rosanshao      
--引用--------------------------------------------------
静静的黎明tm: 我觉得,其实这个吞吐量就是并发量.

如果原来都是一个线程来完成整个用户请求的始末。

现在就是象一个生产者消费者的关系模型。 也是一个队列的模型

生产者就是接受用户的请求,然后他只负责将任务入队到消费者线程池等待的队列中,

实际的工作量没有变, 但不会因为前台的高并发,导致生产者忙碌。

--------------------------------------------------------
你的这个解释是正确的,也没有问题。
现在的问题的,ThreadPool同样使用的处理请求的线程池的线程,使用基于委托的异步同样也是使用了处理请求的线程池中的线程,这样无法提高服务器的并发能力。

#12楼   回复  引用  查看    

2008-11-21 21:32 by weidagang2046      
呵呵,看来楼主是没有搞清楚windows io机制。

问题在这里:

Thread.Sleep(5000);//模拟IO

这个和IO是有区别的。从线程角度这样是模拟很长的CPU操作(线程并没有被释放,虽然不占CPU),不是模拟IO操作。简单说:Thread A通过BeginXXX进行异步,那么正如楼主说所讲,Thread A释放了,但肯定XXX callback需要在Thread B上进行的,如果XXX是CPU型操作,对系统吞吐量并没有好处;但如果XXX是IO的(比如:netstream.beginread),这时Thread A释放了,但Thread B不会马上创建,只有真正IO上有数据的时候,才会创建,也就是说,等待IO的这段时间没有等待的Thread(由windows的IOCP支持,通过少量的IO Thread同时处理大量的IO任务)。Worker Thread只在BeginIO前,和Callback时占用,在BeginIO和Callback之间的时间是交给IO Thread来负责的。这样ThreadPool就可以通过少量的Worker Thread处理大量的请求,前提条件是这些请求是block在IO上的。 不知道说清楚没有。如果我理解不对也欢迎指出!

#13楼[楼主]   回复  引用  查看    

2008-11-21 22:03 by rosanshao      
--引用--------------------------------------------------
weidagang2046
你说得非常正确,我正是在这儿理解有些问题,在IO时,这个时候可以不用线程等待,由Windows的IOCP支持。
但是
public void StartAsyncWork()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
}
private void StartAsyncTask(Object workItemState)
{
Thread.Sleep(5000);//模拟IO ,这个可以不占用线程,线程没有阻塞
....}
不知道你注意没有,代码在IO操作前,都已经ThreadPool.QueueUserWorkItem,已经从线程池中获取了一个线程了。
可能是我对ASP.net异步处理机制还理解不够,不知道具体何时交出占用的线程,何时从线程池中取回线程

#14楼   回复  引用  查看    

2008-11-21 22:16 by weidagang2046      
--引用--------------------------------------------------
不知道你注意没有,代码在IO操作前,都已经ThreadPool.QueueUserWorkItem,已经从线程池中获取了一个线程了。
可能是我对ASP.net异步处理机制还理解不够,不知道具体何时交出占用的线程,何时从线程池中取回线程


--------------------------------------------------------
交出线程很简单,何时return何时交出。调用.net framework定义的BeginIO,比如:netstream.beginread, xxx.beginrequest就会利用iocp,但还是需要你return才行,如果你beginread以后,再sleep一会儿,线程依然不会释放。取回线程的时机是由.net framework根据iocp的事件决定的,这时会从ThreadPool取一个线程来调用callback。 “Worker Thread只在BeginIO前,和Callback时占用”这句话不对,更正:“worker thread在begin io后释放(如果beginio后代码return),直到callback时再占用worker thread”

#15楼   回复  引用  查看    

2008-11-21 23:00 by rockshit      
使用了异步模式,接受的请求数量增加,排队处理的内容就多了,然后cpu使用率提高了,吞吐率就高了。在不使用异步时,cpu的使用率相对就低。

#16楼   回复  引用    

2008-11-22 12:20 by 静静的黎明tm[未注册用户]
--引用--------------------------------------------------
rosanshao: --引用--------------------------------------------------


--------------------------------------------------------
你的这个解释是正确的,也没有问题。
现在的问题的,ThreadPool同样使用的处理请求的线程池的线程,使用基于委托的异步同样也是使用了处理请求的线程池中的线程,这样无法提高服务器的并发能力。
--------------------------------------------------------

突然想到一个很好的例子, 去过卖当劳吧, 前面的收银就是我说的生产者, 他把客人的请求接受完,就交给了后面给客人配食品的的, 然后受理下一个客人。

而实际上假设客人再多, 后面负责给客人备食品的服务员不用很多人。
重点就是,如果是用线程池和异步。 线程池里用很少数量的线程,就可以应对大并发的后续处理请求。

因为 "高并发, 极短处理时间" 的这种请求类型,非常适合使用用异步 + 线程池来完成。后台只需很少的线程就能完成高并发的处理,因为每个请求的处理时间太短了。

使用类似windows完成端口这种机制你会发现在高并发情况下,你的线程数量少得让你惊讶。

#17楼   回复  引用  查看    

2008-11-22 12:42 by DonLiang      
LZ似乎忘记了,创建进程、线程等也是需要花费时间的

#18楼[楼主]   回复  引用  查看    

2008-11-22 15:53 by rosanshao      
--引用--------------------------------------------------
DonLiang: LZ似乎忘记了,创建进程、线程等也是需要花费时间的
--------------------------------------------------------


创建进程、线程等也是需要花费时间的,这是肯定的

使用异步,要看情况,对于需要在服务长时间处理的,如果基本Http长连接的即

时消息传送

#19楼[楼主]   回复  引用  查看    

2008-11-22 15:58 by rosanshao      
--引用--------------------------------------------------
静静的黎明tm: --引用
--------------------------------------------------------

你提到的,原理大家都应该是很清楚的。其实真正的问题是在给客人配食品的与

后面给客人配食品的是如何区分的。

也就是BeginProcessRequest与
public void StartAsyncWork()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncTask), null);
}
执行StartAsyncTask方法的线程是否都是处理请求的线程,如果是的话,那么显然不得提高并发能力

#20楼[楼主]   回复  引用  查看    

2008-11-22 17:13 by rosanshao      
经过几天的测试,终于得到答案,无论是使用基本委托的异步(实质也是使用了线程池中的线程)还是使用线程池,

都无法提高服务器的并发能力,唯一能够提高的办法,就是自定义一个线程池。

记得以前看到自定义线程池的实现,如有知道的,麻烦告知一下。谢谢各位了。

#21楼   回复  引用    

2008-11-22 18:27 by HahahaX[未注册用户]
不懂不要乱说.
要明白ASP.NET的异步模式, 先把WINSOCK的CP的超高并发量的原理弄懂先.

#22楼   回复  引用  查看    

2008-11-22 18:49 by Jeffrey Zhao      
http://www.cnblogs.com/JeffreyZhao/archive/2008/02/24/use-async-operation-properly.html

#23楼[楼主]   回复  引用  查看    

2008-11-22 23:13 by rosanshao      

在服务器端 Web 代码中使用线程和生成异步处理程序

http://msdn.microsoft.com/zh-cn/library/aa686076.aspx

这篇文章说得很清楚
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1338309 t0L0n9Evqug=



相关文章:


相关搜索:
Asp.net.异步.吞吐量

相关链接: