node.js 简介之二

基于事件的Web应用 
  传统的Web表单提交就是典型的基于事件的模式。换句话说,在Web表单里输入了不少数据(用户输入文本框,点选复选框,从列表中选中某些项等等),以后这些数据提交给服务器。这个场景中实际是一个单一的程序事件:使用POST方式将表单数据提交。这也是基于Ajax的Web应用的工做原理。   一次性发送大量数据 
  对于Ajax来讲,是能够和基于事件编程扯上一点关系。客户端和服务器端之间有些交互能够认为是基于事件的。典型的场景是输入一个省市代码,发送请求到服务器得到城市和省的名称。这里经过XmlHttpRequest的Ajax并不须要将不少数据一次性扔给服务器。但这并不能改变大部分web应用都是基于页面刷新这种模式的现状。Ajax已经更普遍的用于不少有意思的视觉相关的交互,快速的做表单验证,无刷新提交数据,这样就能够避免从新载入页面。所以,尽管并未经过提交表单来发起一个真正的POST请求,经过Ajax能够模拟POST表单提交。   坦率的讲,这种传统的Ajax交互方式也阻碍了Ajax程序员的创新。每次发送一个请求时(无论请求的数据多么小),都会在网络里走一个来回。服务器必须针对这个请求做出响应,一般是开辟一个新的进程。所以,若是你真正置身于一个事件模型的环境中作开发,你可能须要经过发起10到15个单独的小请求来保持你的页面和服务器之间的联系,服务器也会为之建立10到15个线程(可能更少,这取决于服务器处理新请求时分配线程池的策略),当这个数量乘以1000或者10000或者100000时(译注:每一个页面须要10个请求,那么越多用户访问这个页面,所发起的请求个数就会愈来愈多),就会出现内存溢出、逻辑交错带来的冲突、网络瘫痪、系统崩溃这些问题。 前端

 

 


  结果是,在大多数场景中,Web应用须要保持对事件的最小依赖。有一个折衷方案,就是服务器端程序的响应返回的不是一个微小的数据片断,而是带有更多冗余数据结构的数据包,一般是JSON数据,这时就又遇到了eval()的问题。问题固然出在eval()身上,但这也和Web自己和服务器线程控制、包括页面和服务器之间的HTTP请求和响应策略(至少在这个场景下)有密不可分的关系。 
  或许有些人对上文提到的问题不觉得然,由于你知道有不少方法来规避直接eval()带来的问题,你会使用诸如JSON.parse()来代替eval()。一样有不少使人信服的论据鼓励咱们当心的使用eval()。这些东东都是值得进一步讨论的。但无论怎样,看一看eval()带来了太多相似栈溢出(Stack Overflow)这类的问题吧,你会发现大部分程序员并未正确或者安全的使用eval()。这着实是一个问题。由于太多菜鸟程序员彷佛根本没有意识到eval()的问题有多严重。 
  不断的发送少许的数据 
  Node带来了架构应用的新思路,咱们能够基于Node采用事件模型来架构Web应用,或者说“小型的”事件模型。换句话说,你应当基于大量的事件发送大量的请求,每一个请求的数据包都很小,或者根据须要从后台抓取少许数据,而不是发送不多的请求,每次请求都带有大量的数据。在不少场景中,大多数状况下你须要唤醒GUI程序(Java Swing程序员的GUI知识储备能够派上用场了)。所以,当用户输入姓氏和名字后,移步到下一个输入框,这时就已经发起了一个请求来验证输入的用户名是否已经存在。省市代码、地址和电话号码的验证也是同理。页面上每发生一个事件,都会产生一个请求和响应。 
  这有什么不一样吗?为何Node能够作到,并规避了已有的线程问题?其实Node并无这么神秘,Node官网充分解释了其哲学: 
  Node的目标是提供一种构建可伸缩的网络应用的方案,在hello world例子中,服务器能够同时处理不少客户端链接。Node和操做系统有一种约定,若是建立了新的连接,操做系统就将通知Node,而后进入休眠。若是有人建立了新的连接,那么它(Node)执行一个回调,每个连接只占用了很是小的(内存)堆栈开销。   Node是无阻塞的,不会出现同源竞争线程的状况(Node很是乐于处理即时的请求,发生了什么事情,那就让他发生吧),新请求到达服务器时,不须要为这个请求单独做什么事情。Node仅仅是清闲的坐在那里等待(请程序员

 

 


求的发生),有请求就处理请求。用很是简单的代码就能够实现,而不用花费程序员宝贵的精力去实现一整套服务器端逻辑。web

没错,混乱不可避免 
  值得一提的是,非阻塞系统带来的问题也会出如今这种编程模式中:一个进程(非线程)等待一个数据存储操做,这时产生了另一个抓取与之无关的数据的操做,这个意外的操做会对现有的等待形成影响(译注:做者的意思是说多个操做同时发生或者没有按照预约顺序发生时,会产生混乱,也就是说,操做自己并非原子性的)。但要注意,大多数基于事件的web编程模式都是“只读的”!你大概也没有遇到过经过“微请求”来修改数据的状况,或者说很是罕见。相反,经过这种请求来验证数据合法性、查询数据的情形则很是常见。这种状况下,最好直接根据请求做响应。数据库自己会做加锁操做,通常来说,一个优秀的数据库彻底能够高效的作到数据操做的加锁解锁,而不用服务器端的程序代码去多作什么。而Node又比操做系统处理线程的保持和释放更加高效,使得服务器没必要单独为“web响应”开辟一个进程。 
  此外,Node也计划实现“进程分支”(process forking),HTML5 Web Workers API为更复杂的进程控制提供了引擎(规范)支持。一样,若是你采用基于事件的模型来架构web应用,你的程序可能至少有100多个场景须要线程的支持。最终你会发现,你的编程思路和思考问题的方式发生了改变,你的注意力将放在服务器端处理请求的逻辑上,而没必要在意Node如何工做。   Node的用武之地 
  这里咱们讨论另一种web开发模式,无论是否是采用了Node、或者是否是采用了基于事件的编程模式,这都可有可无,由于这种模式实在过重要了。简言之:对症下药!归纳讲就是,针对不一样的问题采起不一样的解决方案,而无论这种解决方案是否解决其余问题。   思惟定势 
  不止在web设计领域,在全部编程之中都存在某种思惟定势。能够这么描述这种思惟定势:你学到的、掌握的越多,你能解决的问题就越多,你所掌握的技能的应用场景也就越多。这看起来理所固然,除非你在技术上钻研的更深。没错,学习新的语言和新的工具并普遍使用它总不是坏事。但每每会进入一个误区,就是,由于你了解它,因此你使用它,而不是由于你所掌握的技能和工具是“最适合”你的业务的。 数据库

 

 


  咱们来看一下Ajax,关于Ajax已经有太多太多的讨论了。咱们知道,Ajax为无刷新的快速查询请求提供了可靠的解决方案。而现在由于Ajax的滥用以致于过度替代了传统的表单提交。咱们遇到一个新技术、学习它、掌握它、应用它,而后“滥用它”。毕竟不少业务场景仅仅须要传统的表单提交,而不须要Ajax。提及来简单,实际上还有成千上万的滥用Ajax的案例场景,仅仅由于某个应用的开发工程师对Ajax的盲目尊崇。 
  一样的,Node也面临这样一个问题。当你初识Node发现它的种种好处,就想处处使用它。就会一股脑的将PHP或Perl程序换成Node。结果呢?糟透了。其实你已经害上了强迫症,老是想将Node用于有违其设计初衷的场景中:使用JavaScript提交大量数据给Node,或者经过Node返回给JavaScript大量的JSON数据,交给前端去做eval(),或者干脆使用Node做一个文件服务器用以返回HTML页面或作HTTP重定向。 
  但这些场景均不是Node所擅长的。Node更擅长处理体积小的请求以及基于事件的I/O,使用Node解决客户端和服务器之间的快速沟通,使用表单提交将大量的数据发送给服务器,使用PHP和Perl来处理重型数据库操做以及动态HTML页面的生成。使用Node运行于服务器端来处理体积不大的请求。无论是采用Rails仍是Spring以及各式各样的服务端容器,只要按需索取便可。必定要明白你须要解决的问题是什么,基于此采起最佳解决方案,而不是基于你当下所掌握的技能来解决遇到的问题。   Node的简单的初衷 
  还有最后一点须要注意,当你愈来愈深刻你的编程时,你会发现你没必要每一个工具、API和所使用的框架都达到精通。将刀用在刀刃上,不要将锤子当成钻头来使用。了解每一个工具所适用的场景和能解决的问题,而后找到这个工具的最适合的应用场景。若是你想变成超人式的通才(程序员每每什么都想知道),你离“专家”也就愈来愈远,所谓专家,就是指在一两个方面达到很是精通。固然,每一个老板都但愿能找到超人式的通才,但这种人每每可遇不可求。 
  学习Node可能会有些吃力,可是很是值得的。为何?由于你正在寻求基于JavaScript的web应用的解决方案。这意味着你已有的JavaScript编程技能不会丢掉,当你须要使用PHP或者Perl时,你必须从新学习一门新的语言,而Node没必要如此大动干戈。学习新语言带来的问题比学习他们带来的好处要大的多。 
  学习Node所面临的挑战是,你须要更加活跃思惟,将程序拆成低耦合的小片断,而后像组装数组同样的组装他们。但Node和基于事件的I/O并不能解决全部问题,但肯定的是,不少关键问题,只能依靠Node来解决。编程

相关文章
相关标签/搜索