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


    刚刚开始接触Node.js时, google了很多文章,但发现大部分都是泛泛的介绍安装,配置,以及介绍几个小例子

    有一种雾里观花的感觉,所以非常困惑,不知道Node.js到底解决了什么问题,它的优势到底在哪儿,为什么这么火。

    经过了一番学习之后, 自认为对Node.js的基本原理有了些了解, 于是杜撰了下面这个故事,希望对大家有所帮助,能给大家一点启发

    美丽的七侠镇上有一条美食街,很多著名的饭店都开在这里,有老字号的Apache, PHP, 最近几年火热的Ruby on Rail ,
    还有那些重量级的餐饮集团Websphere, Weblogic 等。

    这些饭店老板根据自己的实力,或多或少的雇佣了一些店小二来招待来客,这些小二干活都非常殷勤,没有一个偷懒耍滑,把顾客招待的舒舒服服, 所以平日里饭馆运转的还不错,相安无事。

    但是随着七侠镇旅游业开发,游客像潮水一样蜂拥而至, 现有的店小二招待不过来了, 到了饭点,每家的门前都排起了长队,游客们吃不上饭,个个怨声载道。


    看到这种情况,有些老板咬了咬牙,在人工费不断上涨的情况下, 多雇了一些小二来帮忙, 无奈总是赶不上顾客增长的速度。

    某一天有个美国老外来到七侠镇上旅游, 也看到了吃不上饭的问题,他仔细分析了一番后发现了一个秘密: 原来这些店都采用了同一套叫做“全程贴心服务”的模式, 这个模式很有意思:

    客人来了以后,马上有个店小二殷勤迎上去,带着找座位,点菜,给后厨下单

    由于后厨做菜需要很长时间,店小二就在客人的旁边等着。

    后厨大喊一声:上菜,店小二马上端到客人面前, 然后站在一边等着客人吃完

    客人说:结账,小二收钱,找钱,送客, 迎接下一位。

    通常这个时候门口都排成了好几百人了

    实在是太贴心了! 导致的结果很明显,饭店有几个店小二,就只能同时接待几个顾客。

    (当然,现实中是没有饭店是这么做的,否则就等着关门吧)

    老外一声不吭的回去了。

    过了几个月, 美食一条街上出现了一个巨火无比的饭馆: Node.js

    虽然这个饭店中人满为患, 可门口竟然没有排队的

    更让人吃惊的是,这个店里声称: 我只需要一个店小二!

    Node.js这个美国老外开的饭店确实只用了一个店小二, 只不过这个小二干活的方式与众不同,他把所有的工作分为两类

    (1) 马上就能干完的,例如迎客,点菜,找座,下单 等等

    (2) 需要等待别人干完才能干的活,例如上菜,结账等

    对(1) 这个小二马上干活

    对(2) 店小二不会等待,他只是说,你弄完了告诉我一声,我会接着干, 然后马上去做第一类工作

    客人来了以后,这个店小二殷勤迎上去,带着找座位,点菜,给后厨下单

    由于后厨做菜需要很长时间,店小二闪电般的离开,去干别的活了,可能是迎客,点菜,找座等,总之是那些不用等待,迅速干完的活

    后厨大喊一声:上菜,这个小二马上端到客人面前,然后离开,干其他活

    客人说:结账,小二收钱,找钱,然后还是迅速闪人,干其他活

    这个唯一的店小二的能力被发挥到了极致,一刻不停,闪电般的在饭店里跑来跑去,因为老板明确的告诉他: 不要等!

    Node.js饭店的基础设施很强大,一旦那些耗时的操作完成,店小二立刻就能知道,飞奔过来马上接着干,如果遇到新的耗时的操作,小二毫不留情的离开。

    就这么简单, Node.js饭店火了,它同时接待客人的数量大大增加,而服务质量保持基本不变。

    OK,这是我杜撰出来的一个不成熟的故事,帮助我来理解Node.js的特点:只用一个线程来处理所有请求,事件驱动编程

    如果我们回过头来再以计算机的视角看一下会更加清楚:

    店小二: 线程

    顾客:http请求

    第一类工作(迎客,找座,下单) : 在服务器端的代码,能够快速执行

    后厨做菜,客人吃饭: 耗时的I/O 操作

    后厨大喊一声:上菜 : 这是一个长时间I/O 操作完成的后所发出的事件

    客人说:结账: 另外一个长时间I/O 操作完成的后所发出的事件

    第二类工作(上菜,结账) : 同样是能快速执行的代码,但是他们需要等待那些耗时的I/O 操作完成才能开始,确切的来说,收到了系统发出的事件以后才开始执行。在Node.js中实际上是在回调函数中来执行的

    下面是Node.js服务模式的伪代码:

    Java代码
    1. 迎客();  
    2. 找座();  
    3. 下单();  
    4. 后厨处理("做菜完成事件", function(){  
    5.     上菜处理;  
    6.     客人吃饭("吃饭完成事件",function(){  
    7.         结账处理;  
    8.         送客();  
    9.     });  
    10. });  

    需要引起注意的是:

    1. 后厨处理()这个函数接受两个参数,一个是事件名,另外一个是匿名的回调函数,事件发生,回调函数才会执行。

        客人吃饭()函数也是类似。

        Node.js 使用的javascript作为服务器端的编程语言,这种回调的方式对于javascript程序员来说,是非常自然的事情,同时从代码的角度来讲,也显得非常清晰。

        另外Node.js使用Chrome的V8引擎来执行javascript,效率非常高

    2. 我们能不能把代码写成这样?

    Java代码
    1. 迎客();  
    2. 找座();  
    3. 下单();  
    4. 后厨处理("做菜完成事件", function(){  
    5.     上菜处理;      
    6. });  
    7. 客人吃饭("吃饭完成事件",function(){  
    8.      结账处理;  
    9. });  
    10. 送客();   

        肯定不行!, 因为Node.js执行"后厨处理()"函数时,只是安插了一个匿名的回调函数在那里,并不会等待(非阻塞I/O),反而马上 会执行“客人吃饭()"函数,所以上述的写法会引起逻辑上的错误:还没上次就开始吃饭了!

    所以写惯了”顺序阻塞I/O“的我们需要改变一下思维方式,进入到事件驱动的世界中来。

    3. 如果某个操作例如“上菜处理” 是个CPU密集型的计算任务,Node.js那个唯一的线程就会忙于执行这个计算任务而被Block 住,就无法响应其他的请求了,带来的后果很严重,整个服务器都无法响应了!  这个时候,需要考虑把这样的代码进行异步处理

    这里我只是粗浅的讨论了Node.js的原理, 哪位同学要想亲自动手试一试的话,这里是一篇非常好的Node入门文章:Node入门

    另外还有两篇深入介绍的文章,非常值得一读(虽然是英文的)

    理解Node.js 事件循环

    理解Node.js

    后记: 第一次看到Node.js, 确实挺吃惊的, 把javascript 作为服务器端的编程语言,只用一个线程来处理所有请求!

    它的作者Ryan Dahl 确实敢想敢干, 再一次体现了美国人的创新精神,非常值得我们学习。

    中国的程序员也需要反思一下,我们为什么没有想到? 我们为什么没有做出来?

  • 相关阅读:
    MapReduce的DBInputFormat使用
    HDFS NameNode与DataNode介绍
    Hadoop的SequenceFile读实例
    Hadoop的SequenceFile读写实例
    MapReduce工作流程详解
    hadoop使用yarn运行mapreduce的过程
    MapReduce的WordCount
    Hadoop的SequenceFile写实例
    Spring的拦截器和监听器
    Hadoop简介
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3165874.html
Copyright © 2020-2023  润新知