1、Node.jsNode.js简介 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。 Node.js是一个事件驱动I/O服务端JavaScript环境(由C+编写),基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。 Node.js的工作原理用户Request用户Request用户RequestNode.js进程Php模型 用户Request用户Request用户RequestAPACHEPHP线程PHP线程PHP线程处理Request处理Request处
2、理RequestNodeJS优缺点及适用场景讨论1 NodeJS的特点2 NodeJS带来的对系统瓶颈的解决方案3 NodeJS的优缺点4 适合NodeJS的场景NodeJS的特点 1. 它是一个Javascript运行环境(C+实现) 2. 依赖于Chrome V8引擎进行代码解释 3. 事件驱动 4. 非阻塞I/O 5. 轻量、可伸缩,适于实时数据交互应用 6. 单进程,单线程 7. 模块化编程 8. 事件轮询(event loop)NodeJS带来的对系统瓶颈的解决方案它的出现确实能为我们解决现实当中系统瓶颈提供了新的思路和方案,下面我们看看它能解决什么问题。 1. 并发连接并发连接 举
3、个例子,想象一个场景,我们在银行排队办理业务,我们看看下面两个模型。(1)系统线程模型:)系统线程模型:这种模型的问题显而易见,服务端只有一个线程,并发请求(用户)到达只能处理一个,其余的要先等待,这就是阻塞,正在享受服务的请求阻塞后面的请求了。(2)多线程、线程池模型)多线程、线程池模型:这个模型已经比上一个有所进步,它调节服务端线程的数量来提高对并发请求的接收和响应,但并发量高的时候,请求仍然需要等待,它有个更严重的问题。到代码层面上来讲,我们看看客户端请求与服务端通讯的过程:服务端与客户端每建立一个连接,都要为这个连接分配一套配套的资源,主要体现为系统内存资源,以PHP为例,维护一个连接
4、可能需要20M的内存。这就是为什么一般并发量一大,就需要多开服务器。那么NodeJS是怎么解决这个问题的呢?我们来看另外一个模型,想象一下我们在快餐店点餐吃饭的场景。(3)异步、事件驱动模型)异步、事件驱动模型我们同样是要发起请求,等待服务器端响应;但是与银行例子不同的是,这次我们点完餐后拿到了一个号码,拿到号码,我们往往会在位置上等待,而在我们后面的请求会继续得到处理,同样是拿了一个号码然后到一旁等待,接待员能一直进行处理。等到饭菜做号了,会喊号码,我们拿到了自己的饭菜,进行后续的处理(吃饭)。这个喊号码的动作在NodeJS中叫做回调(Callback),能在事件(烧菜,I/O)处理完成后继
5、续执行后面的逻辑(吃饭),这体现了NodeJS的显著特点,异步机制、事件驱动整个过程没有阻塞新用户的连接(点餐),也不需要维护已经点餐的用户与厨师的连接。基于这样的机制,理论上陆续有用户请求连接,NodeJS都可以进行响应,因此NodeJS能支持比Java、PHP程序更高的并发量虽然维护事件队列也需要成本,再由于NodeJS是单线程,事件队列越长,得到响应的时间就越长,并发量上去还是会力不从心。总结一下总结一下NodeJS是怎么解决并发连接这个问题的:更改连接到服务器的方式,是怎么解决并发连接这个问题的:更改连接到服务器的方式,每个连接发射(每个连接发射(emit)一个在)一个在NodeJS引
6、擎进程中运行的事件(引擎进程中运行的事件(Event),放),放进事件队列当中,而不是为每个连接生成一个新的进事件队列当中,而不是为每个连接生成一个新的OS线程(并为其分配一些线程(并为其分配一些配套内存)。配套内存)。2. I/O阻塞阻塞NodeJS解决的另外一个问题是I/O阻塞,看看这样的业务场景:需要从多个数据源拉取数据,然后进行处理。(1)串行获取数据,这是我们一般的解决方案,以PHP为例假如获取profile和timeline操作各需要1S,那么串行获取就需要2S。(2)NodeJS非阻塞I/O,发射/监听事件来控制执行过程NodeJS遇到I/O事件会创建一个线程去执行,然后主线程会
7、继续往下执行的,因此,拿profile的动作触发一个I/O事件,马上就会执行拿timeline的动作,两个动作并行执行,假如各需要1S,那么总的时间也就是1S。它们的I/O操作执行完成后,发射一个事件,profile和timeline,事件代理接收后继续往下执行后面的逻辑,这就是NodeJS非阻塞I/O的特点。总结一下:总结一下:Java、PHP也有办法实现并行请求(子线程),但也有办法实现并行请求(子线程),但NodeJS通通过回调函数(过回调函数(Callback)和异步机制会做得很自然。)和异步机制会做得很自然。三三. NodeJS的优缺点的优缺点优点:优点:1. 高并发(最重要的优点,
8、据说可以应付百万级并发)2. 适合I/O密集型应用缺点:缺点:1. 不适合CPU密集型应用;CPU密集型应用给Node带来的挑战主要是:由于JavaScript单线程的原因,如果有长时间运行的计算(比如大循环),将会导致CPU时间片不能释放,使得后续I/O无法发起;解决方案:分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起;2. 只支持单核CPU,不能充分利用CPU3. 可靠性低,一旦代码某个环节崩溃,整个系统都崩溃原因:单进程,单线程解决方案:(1)Nnigx反向代理,负载均衡,开多个进程,绑定多个端口;(2)开多个进程监听同一个端口,使用cluster模块;4.
9、开源组件库质量参差不齐,更新快,向下不兼容5. Debug不方便,错误没有stack trace四四. 适合适合NodeJS的场景的场景1. RESTful API这是NodeJS最理想的应用场景,可以处理数万条连接,本身没有太多的逻辑,只需要请求API,组织数据进行返回即可。它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的API需求。2. 统一Web应用的UI层目前MVC的架构,在某种意义上来说,Web开发有两个UI层,一个是在浏览器里面我们最终看到的,另一个在server端,负责生成和拼
10、接页面。不讨论这种架构是好是坏,但是有另外一种实践,面向服务的架构,更好的做前后端的依赖分离。如果所有的关键业务逻辑都封装成REST调用,就意味着在上层只需要考虑如何用这些REST接口构建具体的应用。那些后端程序员们根本不操心具体数据是如何从一个页面传递到另一个页面的,他们也不用管用户数据更新是通过Ajax异步获取的还是通过刷新页面。3. 大量Ajax请求的应用例如个性化应用,每个用户看到的页面都不一样,缓存失效,需要在页面加载的时候发起Ajax请求,NodeJS能响应大量的并发请求。总而言之,NodeJS适合运用在高并发、I/O密集、少量业务逻辑的场景。花瓣网淘宝开放平台API调用Nodej
11、s版本实现Cnode.org社区成功案例成功案例网易开源基于Node.js的游戏服务器框架pomeloNodeOS(NodeOS是采用NodeJS开发的一款友好的操作系统)Event Loop什么是什么是 Event Loop?Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。JavaScript语言就采用这种机制,来解决单线程运行带来的一些问题。本文参考C. Aaron Cois的Understanding The Node.js Event Loop,解释什么是Event Loop,以及它与JavaScript语言的单线程模型有何关系。想要理解Event Loop,
12、就要从程序的运行模式讲起。运行以后的程序叫做进程(process),一般情况下,一个进程一次只能执行一个任务。如果有很多任务需要执行,不外乎三种解决方法。以JavaScript语言为例,它是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现假死,因为JavaScript停不下来,也就无法响应用户的行为。你也许会问,JavaScript为什么是单线程,难道不能实现为多线程吗?这跟历史有关系。JavaScript从诞生起就是单线程。原因大概是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页
13、脚本语言来说,这就太复杂了。后来就约定俗成,JavaScript为一种单线程语言。(Worker API可以实现多线程,但是JavaScript本身始终是单线程的。)如果某个任务很耗时,比如涉及很多I/O(输入/输出)操作,那么线程的运行大概是下面的样子。上图的绿色部分是程序的运行时间,红色部分是等待时间。可以看到,由于I/O操作很慢,所以这个线程的大部分运行时间都在空等I/O操作的返回结果。这种运行方式称为同步模式(synchronous I/O)或堵塞模式(blocking I/O)。如果采用多线程,同时运行多个任务,那很可能就是下面这样。上图表明,多线程不仅占用多倍的系统资源,也闲置多倍
14、的资源,这显然不合理。Event Loop就是为了解决这个问题而提出的。Wikipedia这样定义:Event Loop是一个程序结构,用于等待和发送消息和事件。简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为主线程;另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为Event Loop线程(可以译为消息线程)。上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主
15、线程就调用事先设定的回调函数,完成整个任务。可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为异步模式(asynchronous I/O)或非堵塞模式(non-blocking mode)。这正是JavaScript语言的运行方式。单线程模型虽然对JavaScript构成了很大的限制,但也因此使它具备了其他语言不具备的优势。如果部署得好,JavaScript程序是不会出现堵塞的,这就是为什么node.js平台可以用很少的资源,应付大流量访问的原因。Node.js 语法语法第一个Node.js程序:Hello World!以下是我们的第一个Node
16、.js程序:console.log(Hello World);保存该文件,并通过 Node.js 来执行:node helloworld.js程序执行后,正常的话,就会在终端输出 Hello World。Node.js 安装配置window和Linux上安装Node.js的方法Node.js安装包及源码下载地址为:http:/www.nodejs.org/download/。根据不同平台系统选择你需要的Node.js安装包。注意:Linux上安装Node.js需要安装Python 2.6 或 2.7 ,不建议安装Python 3.0以上版本。Windowv 上安装Node.jsWindows
17、安装包(.msi) :32 位安装包下载地址 : http:/nodejs.org/dist/v0.10.26/node-v0.10.26-x86.msi64 位安装包下载地址 : http:/nodejs.org/dist/v0.10.26/x64/node-v0.10.26-x64.msi安装步骤:步骤 1 : 双击下载后的安装包 node-v0.10.26-x86.msi,如下所示:安装过程省略。console.log(Hello World);保存该文件,并通过 Node.js 来执行:node helloworld.js程序执行后,正常的话,就会在终端输出 Hello World。N
18、ode.js 创建创建HTTP服务器服务器如果我们使用PHP来编写后端的代码时,需要Apache 或者 Nginx 的HTTP 服务器,并配上 mod_php5 模块和php-cgi。从这个角度看,整个接收 HTTP 请求并提供 Web 页面的需求根本不需 要 PHP 来处理。不过对 Node.js 来说,概念完全不一样了。使用 Node.js 时,我们不仅仅 在实现一个应用,同时还实现了整个 HTTP 服务器。事实上,我们的 Web 应用以及对应的 Web 服务器基本上是一样的。基础的基础的 HTTP 服务器服务器在你的项目的根目录下创建一个叫 server.js 的文件,并写入以下代码:以
19、上代码我们完成了一个可以工作的 HTTP 服务器。使用 node命令 执行以上的代码:接下来,打开浏览器访问 http:/127.0.0.1:8888/,你会看到一个写着 Hello World的网页。分析分析Node.js 的的 HTTP 服务器:服务器:第一行请求(require)Node.js 自带的 http 模块,并且把它赋值给 http 变量。接下来我们调用 http 模块提供的函数: createServer 。这个函数会返回 一个对象,这个对象有一个叫做 listen 的方法,这个方法有一个数值参数, 指定这个 HTTP 服务器监听的端口号。Node.js模块系统模块系统为了让
20、Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C+ 扩展。创建模块创建模块在 Node.js 中,创建一个模块非常简单,如下我们创建一个 main.js 文件,代码如下:以上实例中,代码 require(./hello) 引入了当前目录下的hello.js文件(./ 为当前目录,node.js默认后缀为js)。Node.js 提供了exports 和 require 两个对象,其中
21、exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。接下来我们就来创建hello.js文件,代码如下:在以上示例中,hello.js 通过 exports 对象把 world 作为模块的访 问接口,在 main.js 中通过 require(./hello) 加载这个模块,然后就可以直接访 问main.js 中 exports 对象的成员函数了。Node.js 事件事件Node.js 所有的异步I/O 操作在完成时都会发送一个事件到事件队列。Node.js里面的许多对象都会分发事件:一个net.Server对象会在每次有新连接时
22、分发一个事件, 一个fs.readStream对象会在文件被打开的时候发出一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。 你可以通过require(events);来访问该模块。下面我们用一个简单的例子说明 EventEmitter 的用法:运行这段代码,1秒后控制台输出了 some_event occured。其原理是 event 对象 注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在1000毫秒以后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。Node.js 函数
23、函数在JavaScript中,一个函数可以作为另一个函数接收一个参数。我们可以先定义一个函数,然后传递,也可以在传递参数的地方直接定义函数。Node.js中函数的使用与Javascript类似,举例来说,你可以这样做:以上代码中,我们把 say 函数作为execute函数的第一个变量进行了传递。这里返回的不是 say 的返回值,而是 say 本身!这样一来, say 就变成了execute 中的本地变量 someFunction ,execute可以通过调用 someFunction() (带括号的形式)来使用 say 函数。当然,因为 say 有一个变量, execute 在调用 someF
24、unction 时可以传递这样一个变量。匿名函数匿名函数我们可以把一个函数作为变量传递。但是我们不一定要绕这个先定义,再传递的圈子,我们可以直接在另一个函数的括号中定义和传递这个函数:我们在 execute 接受第一个参数的地方直接定义了我们准备传递给 execute 的函数。用这种方式,我们甚至不用给这个函数起名字,这也是为什么它被叫做匿名函数 。函数传递是如何让函数传递是如何让HTTP服务器工作的服务器工作的带着这些知识,我们再来看看我们简约而不简单的HTTP服务器:现在它看上去应该清晰了很多:我们向 createServer 函数传递了一个匿名函数。用这样的代码也可以达到同样的目的:No
25、de.js 路由路由我们要为路由提供请求的URL和其他需要的GET及POST参数,随后路由需要根据这些数据来执行相应的代码。因此,我们需要查看HTTP请求,从中提取出请求的URL以及GET/POST参数。这一功能应当属于路由还是服务器(甚至作为一个模块自身的功能)确实值得探讨,但这里暂定其为我们的HTTP服务器的功能。我们需要的所有数据都会包含在request对象中,该对象作为onRequest()回调函数的第一个参数传递。但是为了解析这些数据,我们需要额外的Node.JS模块,它们分别是url和querystring模块。THANK YOUSUCCESS2022-5-15当然我们也可以用qu
26、erystring模块来解析POST请求体中的参数,稍后会有演示。现在我们来给onRequest()函数加上一些逻辑,用来找出浏览器请求的URL路径:好了,我们的应用现在可以通过请求的URL路径来区别不同请求了-这使我们得以使用路由(还未完成)来将请求以URL路径为基准映射到处理程序上。Node.js 全局对象全局对象JavaScript 中有一个特殊的对象,称为全局对象(Global Object),它及其所有属性都可 以在程序的任何地方访问,即全局变量。在浏览器JavaScript 中,通常window 是全局对象, 而Node.js 中的全局对象是 global,所有全局变量(除了 gl
27、obal 本身以外)都是 global 对象的属性。我们在Node.js 中能够直接访问到对象通常都是 global 的属性,如 console、process 等,下面逐一介绍。全局对象与全局变量全局对象与全局变量global 最根本的作用是作为全局变量的宿主。按照ECMAScript 的定义,满足以下条 件的变量是全局变量:在最外层定义的变量;全局对象的属性;隐式定义的变量(未定义直接赋值的变量)。当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。需要注 意的是,在Node.js 中你不可能在最外层定义变量,因为所有用户代码都是属于当前模块的, 而模块本身不是最外层上下
28、文。注意:注意: 永远使用var 定义变量以避免引入全局变量,因为全局变量会污染 命名空间,提高代码的耦合风险。processprocess 是一个全局变量,即 global 对象的属性。它用于描述当前Node.js 进程状态 的对象,提供了一个与操作系统的简单接口。通常在你写本地命令行程序的时候,少不了要 和它打交道。下面将会介绍process 对象的一些最常用的成员方法。process.argv是命令行参数数组,第一个元素是 node,第二个元素是脚本文件名, 从第三个元素开始每个元素是一个运行参数。将以上代码存储为argv.js,通过以下命令运行:process.stdout是标准输出流
29、,通常我们使用的 console.log() 向标准输出打印 字符,而 process.stdout.write() 函数提供了更底层的接口。process.stdin是标准输入流,初始时它是被暂停的,要想从标准输入读取数据, 你必须恢复流,并手动编写流的事件响应函数。process.nextTick(callback)的功能是为事件循环设置一项任务,Node.js 会在 下次事件循环调响应时调用 callback。consoleconsole 用于提供控制台标准输出,它是由Internet Explorer 的JScript 引擎提供的调试 工具,后来逐渐成为浏览器的事实标准。Node.js
30、 沿用了这个标准,提供与习惯行为一致的 console 对象,用于向标准输出流(stdout)或标准错误流(stderr)输出字符。 console.log():向标准输出流打印字符并以换行符结束。console.log 接受若干 个参数,如果只有一个参数,则输出这个参数的字符串形式。如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。第一个参数是一个字符串,如果没有 参数,只打印一个换行。运行结果为:Node.js 常用工具常用工具 utilutil 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心JavaScript 的功能 过于精简的不足。util.i
31、nheritsutil.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数。JavaScript 的面向对象特性是基于原型的,与常见的基于类的不同。JavaScript 没有 提供对象继承的语言级别特性,而是通过原型复制来实现的。til.inspectutil.inspect(object,showHidden,depth,colors)是一个将任意对象转换 为字符串的方法,通常用于调试和错误输出。它至少接受一个参数 object,即要转换的对象。util.isArray(object)如果给定的参数 object 是一个数组返回tr
32、ue,否则返回false。util.isRegExp(object)如果给定的参数 object 是一个正则表达式返回true,否则返回false。util.isDate(object)如果给定的参数 object 是一个日期返回true,否则返回false。util.isError(object)如果给定的参数 object 是一个错误对象返回true,否则返回false。Node.js 文件系统文件系统Node.js 文件系统封装在 fs 模块是中,它提供了文件的读取、写入、更名、删除、遍历目录、链接等POSIX 文件系统操作。与其他模块不同的是,fs 模块中所有的操作都提供了异步的和 同
33、步的两个版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。我们以几个函数为代表,介绍 fs 常用的功能,并列出 fs 所有函数 的定义和功能。fs.readFileNode.js读取文件函数语法如下:如果不指 定 encoding,则 callback 就是第二个参数。回调函数提供两个参数 err 和 data,err 表 示有没有错误发生,data 是文件内容。如果指定了 encoding,data 是一个解析后的字符 串,否则 data 将会是以 Buffer 形式表示的二进制数据。例如以下程序,我们从content.txt 中
34、读取数据,但不指定编码:假设content.txt 中的内容是UTF-8 编码的 Text 文本文件示例,运行结果如下:这个程序以二进制的模式读取了文件的内容,data 的值是 Buffer 对象。如果我们给fs.readFile 的 encoding 指定编码:那么运行结果则是:当读取文件出现错误时,err 将会是 Error 对象。如果content.txt 不存在,运行前面 的代码则会出现以下结果:fs.readFileSyncfs.readFileSync(filename, encoding)是 fs.readFile 同步的版本。它接受 的参数和 fs.readFile 相同,而读
35、取到的文件内容会以函数返回值的形式返回。如果有错 误发生,fs 将会抛出异常,你需要使用 try 和 catch 捕捉并处理异常。注意:注意:与同步I/O 函数不同,Node.js 中异步函数大多没有返回值。fs.openfs.open(path, flags, mode, callback(err, fd)是POSIX open 函数的 封装,与C 语言标准库中的 fopen 函数类似。它接受两个必选参数,path 为文件的路径, flags 可以是以下值。r :以读取模式打开文件。r+ :以读写模式打开文件。w :以写入模式打开文件,如果文件不存在则创建。w+ :以读写模式打开文件,如果文
36、件不存在则创建。a :以追加模式打开文件,如果文件不存在则创建。a+ :以读取追加模式打开文件,如果文件不存在则创建fs.readfs.read语法格式如下:参数说明:fd: 读取数据并写入 buffer 指向的缓冲区对象。offset: 是buffer 的写入偏移量。length: 是要从文件中读取的字节数。position: 是文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。callback:回调函数传递bytesRead 和 buffer,分别表示读取的字节数和缓冲区对象。以下是一个使用 fs.open 和 fs.read 的示例。运行结果是:
37、一般来说,除非必要,否则不要使用这种方式读取文件,因为它要求你手动管理缓冲区 和文件指针,尤其是在你不知道文件大小的时候,这将会是一件很麻烦的事情。fs 模块函数表模块函数表Express+MongDB多人博客Redis漂流瓶服务器Meteor微博网站Socket.io+Angular单页应用(聊天室)网络爬虫DemoSocket.io在线聊天室在线聊天室依赖框架依赖框架Socket.io(实现即时通讯,核心)Express(快速构建HTTPweb服务器,实现路由,cookie,session等)Ajs(模板)Angularjs(数据双向绑定更新,封装DOM操作,实现MVC架构)mongDB(
38、数据库)开发工具开发工具Visual Studio 2012(2013)WebStorm目录目录socket.io介绍服务器端和客户端通信设计服务器端实现客户端实现1. socket.io介绍介绍socket.io一个是基于Nodejs架构体系的,支持websocket的协议用于时时通信的一个软件包。socket.io 给跨浏览器构建实时应用提供了完整的封装,socket.io完全由javascript实现。由于socket.io.js文件中会要求flash player版本10.0;请确保此项要求满足socket.io(官网:http:/socket.io/)是一个跨平台,多种连接方式自动切
39、换,做即时通讯方面的开发很方便,而且能和 express提供的传统请求方式很好的结合,即可以在同一个域名,同一个端口提供两种连接方式:request/response, websocket(flashsocket,ajax).Socket.IO旨在让各种浏览器与移动设备上实现实时app功能,模糊化各种传输机制。2. 服务器端和客户端通信设计服务器端和客户端通信设计上图中client1 和 server 描述通信过程,client2描述对其他的客户端,通过广播进行消息通信。client1向server发起连接请求server接受client的连接client1输入登陆用户名server返回欢迎语
40、server通过广播告诉其他在线的用户,client1已登陆client1发送聊天信息server返回聊天信息(可省略)server通过广播告诉其他在线的用户,client1的聊天消息client1关闭连接,退出登陆server通过广播告诉其他在线的用户,client1已退出4. 客户端实现客户端实现CLIENT (INDEX.HTML) var socket = io.connect(http:/localhost); socket.on(news, function (data) console.log(data););socket.emit(my other event, my: dat
41、a );客户端(这里是浏览器)通过引入 即可使用 socket.io 。var socket = io.connect(http:/localhost); 与 http:/localhost 本地服务器建立连接并赋值给 socket 对象,如果是与其他服务器建立连接则只需将 connect() 参数修改为服务器的地址即可,这里 socket.io 客户端和服务器位于同一个服务器上,那么也可以简写为 var socket = io.connect();3. 服务器端实现服务器端实现SERVER (APP.JS)var app = require(express)() , server = req
42、uire(http).createServer(app) , io = require(socket.io).listen(server);server.listen(80);app.get(/, function (req, res) res.sendfile(_dirname + /index.html););io.sockets.on(connection, function (socket) socket.emit(news, hello: world ); socket.on(my other event, function (data) console.log(data); );)
43、;其中 io = require(socket.io).listen(server); 将 socket.io 绑定到服务器上,于是任何连接到该服务器的客户端都具备了实时通信功能。 io.sockets.on(connection, function (socket) . ) 的作用是服务器监听所有客户端,并返回该新连接对象,接下来我们就可以通过该连接对象(socket)与客户端进行通信了。你可以看到不管是服务器还是客户端都有 emit 和 on 这两个函数,可以说 socket.io 的核心就是这两个函数了,通过 emit 和 on 可以轻松地实现服务器与客户端之间的双向通信。emit :用
44、来发射一个事件或者说触发一个事件,第一个参数为事件名,第二个参数为要发送的数据,第三个参数为回调函数(一般省略,如需对方接受到信息后立即得到确认时,则需要用到回调函数)。on :用来监听一个 emit 发射的事件,第一个参数为要监听的事件名,第二个参数为一个匿名函数用来接收对方发来的数据,该匿名函数的第一个参数为接收的数据,若有第二个参数,则为要返回的函数。socket.io 提供了三种默认的事件(客户端和服务器都有):connect 、message 、disconnect 。当与对方建立连接后自动触发 connect 事件,当收到对方发来的数据后触发 message 事件(通常为 sock
45、et.send() 触发),当对方关闭连接后触发 disconnect 事件。此外,socket.io 还支持自定义事件,毕竟以上三种事件应用范围有限,正是通过这些自定义的事件才实现了丰富多彩的通信。最后,需要注意的是,在服务器端区分以下三种情况:socket.emit() :向建立该连接的客户端广播socket.broadcast.emit() :向除去建立该连接的客户端的所有客户端广播io.sockets.emit() :向所有客户端广播,等同于上面两个的和MongoDBMongoDB简介MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种。它在许
46、多场景下可用于替代传统的关系型数据库或键/值存储方式。Mongo使用C+开发。MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似 json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几 乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。 MongoDB简介1.数据结构数据结构 MongoDB使用文档型存储,其数据结构为与JSON类似的BSON结构,而Cassandra支持的是keyvalue式存
47、储,而每个keyvalue还会保存一个时间戳,这个时间戳实际上起到了版本控制的作用。2.索引结构索引结构MongoDB的索引几乎与关系型数据库完全一样,其普通索引、联合索引、唯一索引的意义和实现上都可以参考对MySQL索引的理解。而 Cassandra由于其是一个keyvalue结构的存储,如果你要对value进行条件查找,那么就必须建立反向索引,重新建立一个 valuekey的键值对。Mongo主要解决的是海量数据的访问效率问题,根据官方的文档,当数据量达到50GB以上的时候,Mongo的数据库访问速度是MySQL的10倍以 上。Mongo的并发读写效率不是特别出色,根据官方提供的性能测试表
48、明,大约每秒可以处理0.5万1.5次读写请求。 由于Mongo可以支持复杂的数据结构,而且带有强大的数据查询功能,因此非常受到欢迎,很多项目都考虑用MongoDB来替代MySQL来实现不是 特别复杂的Web应用。 name:lemo,age:12,address:city:suzhou,country:china,code:215000 ,scores:name:english,grade:3.0,name:chinese,grade:2.0特点特点:高性能、易部署、易使用,存储数据非常方便。主要功能特性有:面向集合存储,易存储对象类型的数据。模式自由。支持动态查询。支持完全索引,包含内部对象
49、。支持查询。支持复制和故障恢复。使用高效的二进制数据存储,包括大型对象(如视频等)。自动处理碎片,以支持云计算层次的扩展性支持Python,PHP,Ruby,Java,C,C#,Javascript,Perl及C+语言的驱动程序,社区中也提供了对Erlang及.NET等平台的驱动程序。文件存储格式为BSON(一种JSON的扩展)。可通过网络访问。功能功能:面向集合的存储:适合存储对象及JSON形式的数据。动态查询:Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。完整的索引支持:包括文档内嵌对象及数组。Mongo的查询优化器会分析查询表达式,并生
50、成一个高效的查询计划。查询监视:Mongo包含一个监视工具用于分析数据库操作的性能。复制及自动故障转移:Mongo数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移。高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器。适用场合适用场合:网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避