站长资讯网
最全最丰富的资讯网站

nodejs中I/O是什么意思

在nodejs中,“I/O”是输入输出的意思,通常表示“I/O”操作,“I/O”操作可以分为单线程串行依次执行和多线程并行执行,单线程安装顺序执行,在执行中任何一个稍慢都会导致后续执行代码阻塞。

nodejs中I/O是什么意思

本文操作环境:Windows10系统、nodejs 12.19.0版、Dell G3电脑。

nodejs中I/O是什么意思

对于Nginx服务器,很多人都是比较的熟悉,Nginx采用纯C编写而成,用于做Web服务器,在反向代理和负载均衡等服务方面有很好的优势。Node与Nginx服务器有着相似的地方,都是采用事件驱动。

浏览器中JavaScript在单线程上执行,而且还与UI渲染共用一个线程,JavaScript在执行的时候UI渲染和响应应是出于停滞状态。(如果脚本执行的时间超过100毫秒,用户就会感到页面卡顿)。遇到这些情况,我们就会想到异步的方式消除这些等待的问题,对于异步和同步的概念就不做介绍了。

接下来我们具体的来了解一下NodeJS的事件驱动和非阻塞I/O这些特点,了解这些对于我们更好的学习NodeJS开发和构建高性能的Web平台有更加深远的意义。

1.I/O操作概述:

I/O操作对于任何一个开发者来说都不会陌生,现在我们就简单的谈一下NodeJS的I.O操作。I/O操作分为:单线程串行依次执行;多线程并行执行。这两种方式各有优势和缺点,多线程的代价在于创建线程和执行期线程上下文切换的开销较大,并且多线程面临锁、状态同步的问题。单线程安装顺序执行,在执行中任何一个稍慢都会导致后续执行代码阻塞。对于任务的串行执行(概念上类似于同步执行)和任务的并行执行的描述有如下图:

nodejs中I/O是什么意思

在NodeJS中利用单线程,远离死锁、状态同步问题,利用异步I/O,让单线程远离阻塞,以便更好的使用CPU。异步I/O是期望I/O的调用不再阻塞后续运算,将原有等待I/O完成这段时间分配给其他需要的业务去执行。   

很多时候一些开发者对异步/同步和阻塞/非阻塞的概念有些分不清,这两者没有什么关联。阻塞I/O是调用之后一定要等到系统内核层面完成所有操作后,调用才结束。非阻塞I/O是在调用后立即返回。关于阻塞I/O和非阻塞I/O有如下图:

nodejs中I/O是什么意思

2.NodeJS异步I/O解析:

事件循环:在进程启动时,Node会创建一个类似于while(true)的循环,每执行一次循环体的过程称为Tick,每个Tick的过程就是查看是否有时间待处理。

观察者:每个时间循环中有一个或多个观察者,判断是否有事件要处理的过程就是向这些观察者询问是否又要处理的事件。

请求对象:从JavaScript发起调用到内核执行完I/O操作的过渡过程中,存在一种中间产物,就是请求对象。

I/O线程池:组装好请求、送入I/O线程池等待执行,完成第一步I/O操作,进入第二部分回调通知。(在Windows中,线程池中的I/O操作调用完毕之后,会将获取的结果存在req->result属性上,然后调用PostQueuedCompletionStatus()通知IOCP,告知当前对象操作已经完成。)

异步I/O有如下图:

nodejs中I/O是什么意思

三.NodeJS异步编程实例:

前面介绍了异步I/O的相关概念,这里提供一个异步I/O操作的实例:

var config = require('./config.json'); var fs = require("fs"); var http = require('http'); var url_module = require("url"); http.createServer(function (request, response) { var key = url_module.parse(request.url).query.replace('key=', ''); switch (request.method) {    case 'GET':  // Asynchronous Response Generation        fs.readFile(config.dataPath + key, 'utf8', function(err, value) {            if (err) {                // Return File Not Found if file hasn't yet been created                response.writeHead(404, {'Content-Type': 'text/plain'});                response.end("The file (" + config.dataPath + key + ") does not yet exist.");            } else {                // If the file exists, read it and return the sorted contents                var sorted = value.split(config.sortSplitString).sort().join('');                response.writeHead(200, {'Content-Type': 'text/plain'});                response.end(sorted);            }        });        break;    case 'POST':  // Synchronously append POSTed data to a file        var postData = '';        request            .on('data', function (data) {                postData += data;            })            .on('end', function () {                fs.appendFile(config.dataPath + key, postData, function(err) {                    if (err) {                        //  Return error if unable to create/append to the file                        response.writeHead(400, {'Content-Type': 'text/plain'});                        response.end('Error: Unable to write file: ' + err);                    } else {                        //  Write or append posted data to a file, return "success" response                        response.writeHead(200, {'Content-Type': 'text/plain'});                        response.end('success');                    }                });            });        break;    default:        response.writeHead(400, {'Content-Type': 'text/plain'});        response.end("Error: Bad HTTP method: " + request.method); } }).listen(config.serverPort); console.log('synchronous server is running: ', config.serverPort);

推荐学习:《nodejs视频教程》

赞(0)
分享到: 更多 (0)