Node.js NodeJS 我只需要一个店小二

zzz6519003 · 2019年11月08日 · 5155 次阅读

作者:千夜同学 时间:2012-07-01 分类:编程

http://70data.net/1281.html

美丽的七侠镇上有一条美食街,很多著名的饭店都开在这里,有老字号的 Apache、PHP, 最近几年火热的 Ruby on Rail,还有那些重量级的餐饮集团 Websphere、Weblogic 等。 这些饭店老板根据自己的实力,或多或少的雇佣了一些店小二来招待来客,这些小二干活都非常殷勤,没有一个偷懒耍滑,把顾客招待的舒舒服服,所以平日里饭馆运转的还不错,相安无事。 但是随着《武林外传》的拍摄和播放,七侠镇旅游业大爆发,游客像潮水一样蜂拥而至,现有的店小二招待不过来了,到了饭点,每家的门前都排起了长队,游客们吃不上饭,个个怨声载道。 看到这种情况,有些老板咬了咬牙,在人工费不断上涨的情况下,多雇了一些小二来帮忙,无奈总是赶不上顾客增长的速度。 某一天有个美国老外来到七侠镇上旅游,也看到了吃不上饭的问题,他仔细分析了一番后发现了一个秘密:原来这些店都采用了同一套叫做“全程贴心服务”的模式,这个模式很有意思:客人来了以后,马上有个店小二殷勤迎上去,带着找座位,点菜,给后厨下单。由于后厨做菜需要很长时间,店小二就在客人的旁边等着。后厨一摇铃铛,大喊一声:上菜,店小二马上端到客人面前,然后站在一边等着客人吃完。客人说:结账,小二收钱,找钱,送客,迎接下一位。通常这个时候门口都排成了好几百人了! 这个 VIP 服务实在是太贴心了!导致的结果很明显,饭店有几个店小二,就只能同时接待几个顾客。 老外一声不吭的回去了。 过了几个月,美食一条街上出现了一个巨火无比的饭馆:NodeJS 虽然这个饭店中人满为患,可门口竟然没有排队的! 更让人吃惊的是,这个店里声称:我只需要一个店小二。

NodeJS 这个美国老外开的饭店确实只用了一个店小二,只不过这个小二干活的方式与众不同,他把所有的工作分为两类: (1) 马上就能干完的,例如迎客,点菜,找座,下单等等。 (2) 需要等待别人干完才能干的活,例如上菜,结账等。 对 (1) 这个小二马上干活。 对 (2) 店小二不会等待,他只是告诉别人说,你弄完了告诉我一声,我会接着干,然后马上去做第一类工作。 客人来了以后,这个店小二殷勤迎上去,带着找座位,点菜,给后厨下单。 由于后厨做菜需要很长时间,店小二闪电般的离开,去干别的活了,可能是迎客,点菜,找座等,总之是那些不用等待,迅速干完的活。 后厨大喊一声:上菜,这个小二马上端到客人面前,然后离开,干其他活。 客人说:结账,小二收钱,找钱,然后还是迅速闪人,干其他活。 这个唯一的店小二的能力被发挥到了极致,一刻不停,闪电般的在饭店里跑来跑去,因为老板明确的告诉他:不要等! NodeJS 饭店的基础设施很强大,一旦那些耗时的操作完成,店小二立刻就能知道,飞奔过来马上接着干,如果遇到新的耗时的操作,小二毫不留情的离开。 就这么简单,NodeJS 饭店火了,它同时接待客人的数量大大增加,而服务质量保持基本不变。 这是我杜撰出来的一个不成熟的故事,帮助我来理解 NodeJS 的特点:只用一个线程来处理所有请求,事件驱动编程。 如果我们回过头来再以计算机的视角看一下会更加清楚: 店小二:线程 顾客:HTTP 请求 第一类工作 (迎客,找座,下单):在服务器端的代码,能够快速执行。 后厨做菜,客人吃饭:耗时的 I/O 操作。 后厨大喊一声:上菜:这是一个长时间 I/O 操作完成的后所发出的事件。 客人说:结账:另外一个长时间 I/O 操作完成的后所发出的事件。 第二类工作 (上菜,结账):同样是能快速执行的代码,但是他们需要等待那些耗时的 I/O。 操作完成才能开始,确切的来说,收到了系统发出的事件以后才开始执行。在 NodeJS 中实际上是在回调函数中来执行的。 下面是 NodeJS 服务模式的伪代码:

迎客 (); 找座 (); 下单 (); 后厨处理 ("做菜完成事件",function(){ 上菜处理 (); 客人吃饭 ("吃饭完成事件",function(){ 结账处理 (); 送客 (); }); }); 需要引起注意的是: 1.后厨处理()这个函数接受两个参数,一个是事件名,另外一个是匿名的回调函数,事件发生,回调函数才会执行。客人吃饭()函数也是类似。 NodeJS 使用的 JavaScript 作为服务器端的编程语言,这种回调的方式对于 JavaScript 程序员来说,是非常自然的事情,同时从代码的角度来讲,也显得非常清晰。另外 NodeJS 使用 Chrome 的 V8 引擎来执行 JavaScript 效率非常高 2.我们能不能把代码写成这样:

迎客 (); 找座 (); 下单 (); 后厨处理 ("做菜完成事件",function(){ 上菜处理 (); }); 客人吃饭 ("吃饭完成事件",function(){ 结账处理 (); }); 送客 (); 肯定不行。因为 NodeJS 执行"后厨处理 ()"函数时,只是安插了一个匿名的回调函数在那里,并不会等待(非阻塞 I/O),反而马上会执行"客人吃饭 ()"函数,所以上述的写法会引起逻辑上的错误:还没上菜就开始吃饭了! 所以写惯了"顺序阻塞 I/O"的我们需要改变一下思维方式,进入到事件驱动的世界中来。 3.如果某个操作例如"上菜处理"是个 CPU 密集型的计算任务,NodeJS 那个唯一的线程就会忙于执行这个计算任务而被阻塞住,就无法响应其他的请求了,带来的后果很严重,整个服务器都无法响应了!这个时候,需要考虑把这样的代码进行异步处理,也变成 NodeJS 所擅长的事件驱动的方式。

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号