node介紹

node 特點

  • 單線程
    傳統(tǒng)的java是為每個連接建一個線程绝编,每個線程需要耗費大約2MB內(nèi)存僻澎。如果需要處理大量的并發(fā)就需要大量的機器。而node只是有一個線程瓮增,當有客戶端連接了怎棱,就觸發(fā)一個內(nèi)部事件,通過非阻塞I/O绷跑、事件驅(qū)動機制拳恋,讓Node.js程序宏觀上也是并行的。
  • 非阻塞I/O
    理論上單線程處理砸捏,在執(zhí)行I/O操作時谬运,整個線程會掛起,阻塞垦藏,等到結(jié)果返回后梆暖,才能執(zhí)行后面的代碼,而在node中I/O是非 阻塞的掂骏,當執(zhí)行I/O時轰驳,只是把I/O丟給libuv處理,繼續(xù)執(zhí)行后面的代碼弟灼,當某個I/O執(zhí)行完畢時级解,將以事件的形式通知node線程,線程執(zhí)行這個事件的回調(diào)函數(shù)田绑。
  • 事件驅(qū)動
    客戶端請求建立連接勤哗,會觸發(fā)相應的事件。在Node中掩驱,在一個時刻芒划,只能執(zhí)行一個事件回調(diào)函數(shù)冬竟,但是在執(zhí)行一個事件回調(diào)函數(shù)的中途,可以轉(zhuǎn)而處理其他事件(比如民逼,又有新用戶連接了)泵殴,然后返回繼續(xù)執(zhí)行原事件的回調(diào)函數(shù),這種處理機制缴挖,稱為“事件循環(huán)”袋狞。

創(chuàng)建一個Server

'use strict';
const http = require('http');
http.createServer(function(req, res){
    res.writeHead(200, {'Content-Type':'text/html; charset= UTF-8; '});
    res.end('Hello World!');
}).listen(8080);

?  ~ curl 127.0.0.1:8080
Hello World!%

這就是一個最簡單的helloWorld,那我們客戶端請求到server是如何運行的呢映屋?

1.http模塊在node 中http模塊有2個一個是http-client苟鸯,一個是http-server
2.http模塊是繼承與net模塊,net模塊是繼承與events
3.events只提供了 events.EventEmitter棚点。EventEmitter 的核心就是事件觸發(fā)與事件監(jiān)聽器功能的封裝
4.此時的http就擁有了事件的監(jiān)聽與觸發(fā)功能

實現(xiàn)原理

我們通過代碼http.createServer方法

// http.js
function createServer(opts, requestListener) {
  return new Server(opts, requestListener);
}
//http-server.js
function Server(options, requestListener) {
    /*省略代碼*/
  if (requestListener) {
    this.on('request', requestListener);  
  }
  this.on('connection', connectionListener);
}

核心代碼是注冊了2個方法一個request早处,一個connection方法

connection 方法是在tcp的3次握手會被調(diào)用,在client-server建立連接成功之后瘫析,

function connectionListenerInternal(server, socket) {
  debug('SERVER new http connection');
/**省略代碼**/
  parser.onIncoming = parserOnIncoming.bind(undefined, server, socket, state);

  // We are consuming socket, so it won't get any actual data
  socket.on('resume', onSocketResume);
  socket.on('pause', onSocketPause);

  // Override on to unconsume on `data`, `readable` listeners
  socket.on = socketOnWrap;

  // We only consume the socket if it has never been consumed before.
  if (socket._handle) {
    var external = socket._handle._externalStream;
    if (!socket._handle._consumed && external) {
      parser._consumed = true;
      socket._handle._consumed = true;
      parser.consume(external);
    }
  }
  parser[kOnExecute] =
    onParserExecute.bind(undefined, server, socket, parser, state);

  socket._paused = false;
}

tcp建立成功砌梆,然后server就需要解析數(shù)據(jù),生成一個req與res贬循,同時要emit觸發(fā)request方法咸包,這樣就回到了我們的http.createServer(callback)方法

function parserOnIncoming(server, socket, state, req, keepAlive) {
  resetSocketTimeout(server, socket, state);

  if (req.upgrade) {
    req.upgrade = req.method === 'CONNECT' ||
                  server.listenerCount('upgrade') > 0;
    if (req.upgrade)
      return 2;
  }

  state.incoming.push(req);

  // If the writable end isn't consuming, then stop reading
  // so that we don't become overwhelmed by a flood of
  // pipelined requests that may never be resolved.
  if (!socket._paused) {
    var ws = socket._writableState;
    if (ws.needDrain || state.outgoingData >= socket.writableHighWaterMark) {
      socket._paused = true;
      // We also need to pause the parser, but don't do that until after
      // the call to execute, because we may still be processing the last
      // chunk.
      socket.pause();
    }
  }

  var res = new server[kServerResponse](req);
  res._onPendingData = updateOutgoingData.bind(undefined, socket, state);

  res.shouldKeepAlive = keepAlive;
  DTRACE_HTTP_SERVER_REQUEST(req, socket);
  COUNTER_HTTP_SERVER_REQUEST();

  if (socket._httpMessage) {
    // There are already pending outgoing res, append.
    state.outgoing.push(res);
  } else {
    res.assignSocket(socket);
  }

  // When we're finished writing the response, check if this is the last
  // response, if so destroy the socket.
  res.on('finish',
         resOnFinish.bind(undefined, req, res, socket, state, server));

  if (req.headers.expect !== undefined &&
      (req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) {
    if (continueExpression.test(req.headers.expect)) {
      res._expect_continue = true;

      if (server.listenerCount('checkContinue') > 0) {
        server.emit('checkContinue', req, res);
      } else {
        res.writeContinue();
        server.emit('request', req, res);
      }
    } else if (server.listenerCount('checkExpectation') > 0) {
      server.emit('checkExpectation', req, res);
    } else {
      res.writeHead(417);
      res.end();
    }
  } else {
    server.emit('request', req, res);
  }
  return 0;  // No special treatment.
}
關鍵代碼 server.emit('request', req, res);

這樣我們就監(jiān)聽到了客戶端的請求。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杖虾,一起剝皮案震驚了整個濱河市烂瘫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奇适,老刑警劉巖坟比,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嚷往,居然都是意外死亡葛账,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門皮仁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來籍琳,“玉大人,你說我怎么就攤上這事贷祈∏骷保” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵付燥,是天一觀的道長。 經(jīng)常有香客問我愈犹,道長键科,這世上最難降的妖魔是什么闻丑? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮勋颖,結(jié)果婚禮上嗦嗡,老公的妹妹穿的比我還像新娘。我一直安慰自己饭玲,他們只是感情好侥祭,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著茄厘,像睡著了一般矮冬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上次哈,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天胎署,我揣著相機與錄音,去河邊找鬼窑滞。 笑死琼牧,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的哀卫。 我是一名探鬼主播巨坊,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼此改!你這毒婦竟也來了趾撵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤带斑,失蹤者是張志新(化名)和其女友劉穎鼓寺,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勋磕,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡妈候,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挂滓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苦银。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖赶站,靈堂內(nèi)的尸體忽然破棺而出幔虏,到底是詐尸還是另有隱情,我是刑警寧澤贝椿,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布想括,位于F島的核電站,受9級特大地震影響烙博,放射性物質(zhì)發(fā)生泄漏瑟蜈。R本人自食惡果不足惜烟逊,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铺根。 院中可真熱鬧宪躯,春花似錦、人聲如沸位迂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掂林。三九已至臣缀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間党饮,已是汗流浹背肝陪。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留刑顺,地道東北人氯窍。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像蹲堂,于是被迫代替她去往敵國和親狼讨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • ?然后得到日本刻板的父親柒竞,把孩子放在鍋里蒸汗政供,無語,想把它們撐死朽基,她們得到了風的幫助著布隔,小屋里峰,為他們提供了一個...
    海哥0001閱讀 183評論 0 0
  • 在這一年里,很難統(tǒng)計殺殺君總共聽了多少首歐美音樂霎俩,不過數(shù)字確實不在少數(shù)哀军。其中,不乏有不對味的打却,聽上幾遍也就從資料庫...
    殺殺君閱讀 506評論 0 2
  • 姓名:趙麗娟 公司:叢迪服裝有限公司 【日精進打卡第82天】 【知~學習】 《六項精進》大綱2遍杉适,共212遍; 《...
    阿詩瑪_6209閱讀 212評論 0 0
  • 2018年,7月28號早,4.50鬧鐘準時把我從睡夢中叫醒捌肴,起床后的第一件事就是去廁所蹬叭,肚子隱約有點疼毯侦,出了屋門走...
    珍惜愛_08bb閱讀 214評論 0 1