[原文發表地址]Installing and Running node.js applications within IIS on Windows - Are you mad?php
[原文發表時間]2011-08-28 08:03html
咱們團隊中的一些成員正在努力優化node.js在Windows上的運行效果。你可能會問一些問題。node
首先,node.js是什麼?git
若是你不熟悉node.js,我要說這是一個煊赫一時的新型web編程工具包。要是你沒據說過會讓你以爲本身很過期,就好像幾年前Rail上的Ruby那樣風靡。同行們把它稱之爲「Node」,簡單來講是服務器端的JavaScript。若是你在客戶端作一系列的JavaScript,並且時常一作就是一成天,那爲何不在服務器端試試呢。學起來應該很簡單,我猜測是這樣的。github
若是你是一個ASP.NET編程員,你能夠把node.js當作是用JavaScript寫成的IhttpHandler。其實它的等級更低, 它連HttpHandler都不是,這裏我只是想作一個類比。Brett McLaughlin寫的一篇有關Node.js 更多細節以及概述的文章很不錯。文章的副標題就是「Node不可能解決全部的問題,但的確能夠解決一些重要的問題」,這個描述很貼切。web
更新1:爲何node.js那麼重要?數據庫
爲何咱們須要node呢?node有許多有趣的部分。它使用的是很是快速的JavaScript引擎V8,更重要的是它的I/O是異步的,並且與傳統同步代碼造成鮮明對比的是它的事件驅動。編程
舉例來講,ASP.NET中的HttpHandler要用幾秒來「作些什麼」(如獲取文件,訪問服務等)以下所示:緩存
1: public class SimpleHandler : IHttpHandler
2: {
3: public void ProcessRequest(HttpContext context)
4: {
5: Thread.Sleep(2000); //Do something that takes a while
6: context.Response.Write("Hello from SimpleHandler");
7: }
8:
9: public bool IsReusable { get { return true; } }
10: }
這用來處理大部分狀況仍是很好的。不過,當我用測試工具同時加載1000個虛擬客戶端打算測試它的極限時,我一秒鐘連60個請求都獲取不到。請求線程和工做線程同時進行時,你們都在排隊。我把ASP.NET程序池的資源都消耗光了。若是工做線程結束後能及時回調(Call Back)那就太完美了。這就好像在等待技術支持同樣,你只能被迫等待一個結果。他們要是能在他們準備好以後及時通知你這不是很好嗎?安全
ASP.NET一直能夠(看看MSDN上一篇發表於2003年關於Async Handlers的 文章)經過IHttpAsyncHandler作不少工做,但過程繁複一點並且幾乎沒什麼人知道。有了.NET內建的Async CTP和Task庫,你就能在IhttpAsyncHandler的頂部建立更好的抽象元素。Ayende對AbstractAsyncHandler有一個簡單的實例(有不少相似的應用,好比在咱們本身的工具裏,MVC裏,還有SignalR裏(未來還會有更多)),讓咱們能夠用來作相似的工做。這個實例還能夠作一些更復雜細小的事情,好比文件IO,數據庫 IO或者調用web服務。這是一個再簡單不過的例子,可能並無徹底同步Node,但基本仍是能夠的。並且,看上去仍是不錯的。
1: public class SimpleAsyncAyendeHandler : AbstractAsyncHandler
2: {
3: protected override async Task ProcessRequestAsync(HttpContext context)
4: {
5: await TaskEx.Delay(2000);
6: await context.Response.Output.WriteAsync("Hello from Ayende and Scott");
7: }
8: }
一樣是同時處理1000個虛擬客戶,我在一秒內收到了500個請求,每一個請求大約須要2秒來完成,這樣的效率是合理並能夠接受的。若是咱們不是在乾等,而是在作I/O或者其餘更復雜的長時間運行工做的話,效果會比第一個例子更好。有了上述兩行代碼的支持,以及Ayende的簡單實例,在.NET中作異步代碼和並行比之前方便許多。在Node中這樣的東西既簡單又優雅,的確是很吸引人的。
Node最擅長異步了,經過JavaScript進行回調來實現完整的異步。你已經會在客戶端使用JavaScript調用和事件了,那爲何不融會貫通到服務器端呢?這裏提供 Marc Fasel針對這個話題的一篇博文實例。
首先, 經過Marc實現一些同步文件工做:
1: var fs = require('fs'), filenames, i, processId;
2:
3: filenames = fs.readdirSync(".");
4: for (i = 0; i < filenames.length; i++) {
5: console.log(filenames[i]);
6: }
7: console.log("Ready.");
8:
9: processId = process.getuid();
還有用異步來完成一樣的工做,看上去很熟悉吧!
1: var fs = require('fs'), processId;
2:
3: fs.readdir(".", function (err, filenames) {
4: var i;
5: for (i = 0; i < filenames.length; i++) {
6: console.log(filenames[i]);
7: }
8: console.log("Ready.");
9: });
10:
11: processId = process.getuid();
I/O開始後,回調函數則由I/O的執行的結果決定。很強大吧。
爲何要在Windows和IIS上運行node.js?
Tomasz Janczuk最近在作iisnode項目。你可能會認爲Windows和node徹底不搭邊。「這是不對的!他們在想什麼?IIS都是.NET相關的東西?」那麼你能夠回憶一下幾年前我在CodeMash上說的,有關IIS7和PHP,當時我也作了個截屏展現了IIS7, PHP和 FastCGI是怎麼在一秒內聚齊上千的請求的。IIS的工做人員,Windows的工做人員,Azure的工做人員都但願Windows上全部東西都會運行順暢。記住,咱們是賣Windows的,它能夠作越多的事對咱們來講是好事。
幹嗎還要讓node在IIS上運行呢?
Tomasz的回答是我見過最棒的:
使用iisnode模塊在IIS中託管node.js應用程序來取代自託管node.exe進程的優點在於:
· 進程管理。 Iisnode模式注重node.exe進程的長期管理,可以更簡潔地改善總體可靠性。你無需實現用來運行,中止或者顯示進程的基礎工具。
· 多核服務器上的可擴展性。因爲node.exe是一個單線進程,只可適用於單核CPU。而iisnode模塊容許每一個應用中建立多個node.exe進程,並根據HTTP流量調整使其負載平衡。,從而充分能夠發揮服務器CPU性能,無需額外的基礎代碼。
· 自動更新。Iisnode模塊保證了node.js應用隨時保持更新(好比,在腳本文件變動時就會更新),node.exe進程獲得循環。舊版本的應用能正確地完成正在進行中的請求執行,而全部的新請求都會分派到應用的最新版本。
· 經過HTTP訪問日誌。Iisnode模塊提供經過HTTP訪問node.exe進程中的輸出。(好比,由console.log調用生成的輸出)。這個功能是幫你調試在遠程服務器上的node.js應用程序問題的關鍵。
· 與其餘內容類型相連。 Iisnode模塊與IIS相融,讓一個單一的web頁面可以涵蓋許多內容類型。好比,一個單一的頁面能夠包含一個node.js應用,統計HTML,JavaScript文件,PHP應用和ASP.NET應用。這就讓用戶能隨意挑選最適合的工具,並未已有應用完成遷移。
· 只需改變少部分node.js應用代碼。 Iisnode模塊支持最少的改動來託管現有HTTP node.js應用。你只需經過process.env.PORT環境變量把HTTP服務器列出的地址變爲iisnode提供的地址就能夠了。
融合管理體驗。 issnode模塊徹底集成IIS配置系統,並使用相同的工具和機制,相似於IIS其它組件的配置和維護。
除了有利於iisnode模塊中特定的點,在IIS中託管node.js應用還能讓開發者從一系列IIS功能中獲益匪淺,包括:
都很是有說服力,但在我看來,最有趣的要數一體化了。Iisnode模塊是一個合理的IIS模塊,就像ASP.NET和PHP同樣。這就意味着你能夠在一個單一的網站上看到多種內容。正如上述:
好比,一個單一的頁站能夠包含一個node.js應用,統計HTML,JavaScript文件,PHP應用和ASP.NET應用。
一些同仁們一聽到我說,你能夠在同一個AppPool中使用ASP.NET WebForms和ASP.NET MVC就好像「混血兒」同樣,就會瘋狂起來。親愛的讀者,你們都沒有意識到IIS的強大和靈活性。當你插入像node同樣的新東西,但仍是按舊方法來操做時,它仍然會延續全部包含的優勢。
好吧,你說服我了,那我要怎麼在Windows上運行node.js呢?
我假定你運行的是IIS7.
· 去 下載node.exe,放在 c:\node
· 去 下載iisnode.
· 解壓iisnode壓縮包,解壓到\inetpub\iisnode
· (只是個人建議,未必是最好的位置)
· 以管理員身份在命令行中運行install.bat。
Install.bat將會:
· 從你安裝的IIS中取消註冊已有的「iisnode」全局模塊,若是你已經註冊過的話。
· 在你的安裝的IIS中註冊iisnode爲本地模塊
· 安裝「iisnode」模塊配置文件
· 從applicationHost.config中的system.webServer組移除現有「iisnode」部分
· 在applicationHost.config中的system.webServer組添加新的「iisnode」部分
· 若是有iisnode web應用,直接刪除
· 爲IIS添加新的iisnode站點
沒有保證!要當心,你是在邊緣行走。記住,你只是在偶然看到的博客上看到這篇文章。
警告:我搞不清楚正確的AppPool和文件系統權限,因此我直接給了我本地AppPool「SYSTEM」的權限。這很糟糕,都是個人錯。我在iisnode GitHub上寫下了問題,等他們有回覆時我會想辦法修復而後更新的。
我爲node作了個新的AppPool,給了它SYSTEM的訪問權限,而後將Node Site分配給這個新的AppPool。你的站點看上去就是這樣的:
若是你在IIS7的這個頁面上點擊這個模塊,你將會看到iisnode是本地模塊:
如今,你能夠點擊http://localhost/node/helloworld/hello.js 而後獲得回饋:
Hello, world! [helloworld sample]
內容很簡單:
1: var http = require('http');
2:
3: http.createServer(function (req, res) {
4: res.writeHead(200, {'Content-Type': 'text/plain'});
5: res.end('Hello, world! [helloworld sample]');
6: }).listen(process.env.PORT);
很棒吧。
玩玩WCAT(Web容量分析工具)和node。
免責聲明:先說清楚,這只是玩玩。不過爲了展現它的確能用,並且運行的速度很快。我作的不是基準內容,我也沒說過「這個運行起來比別的工具好」。記住,他們最近剛剛起步,把node遷移到Windows,Tomasz和他的朋友們最近纔開始作。因此不要指望過高。話說回來,他們如今作成的內容已經很歎爲觀止了。
我真是有些激動了。我是說把一個新的東西安裝到另外一個新的東西上,而後只運行一次就成功了。我作完一系列基礎工做以後,我想作一些簡單的壓力測試看看你們作了些什麼。
首先,我安裝了WCAT,一款IIS團隊開發的免費Web容量分析工具。
1. WCAT 6.3 x86
2. WCAT 6.3 x64
警告:這是一個僅支持命令行的工具,運行起來真的有點小家子氣。有點混亂,設置安裝也花了我點時間。如下是我安裝的步驟。都是從管理者權限的命令提示符中執行的。注意我是在同一臺機器上作的,記住這是GOM 。
1. cscript //H:Cscript
2. wcat.wsf –terminate –update –clients localhost
3. 而後我建了一個文件夾命名爲\nodetests,而後把這三個文件放了進去。
wcat.bat
pushd C:\Users\Scott\Desktop\nodetests
"c:\program files\wcat\wcat.wsf" -terminate -run -clients localhost -f settings.ubr -t nodescenario.ubr -s localhost -singleip -o C:\Users\Scott\Desktop\nodetests
pause
nodescenario.ubr (你能夠隨意命名)
這也很簡單。它會被4個示例程序一一調用。
1: scenario
2: {
3: name = "node_fun";
4:
5: warmup = 30;
6: duration = 90;
7: cooldown = 30;
8:
9: default
10:
11: setheader
12: {
13: name = "Connection";
14: value = "keep-alive";
15: }
16: setheader
17: {
18: name = "Host";
19: value = server();
20: }
21: version = HTTP11;
22: statuscode = 200;
23: close = ka;
24: }
25:
26: transaction
27: {
28: id = "foo";
29: weight = 1000;
30: request
31: {
32: url = "/node/logging/hello.js";
33: }
34: }
35: transaction
36: {
37: id = "bar";
38: weight = 2000;
39: request
40: {
41: url = "/node/helloworld/hello.js";
42: }
43: }
44: transaction
45: {
46: id = "baz";
47: weight = 2000;
48: request
49: {
50: url = "/node/defaultdocument/";
51: }
52: }
53: transaction
54: {
55: id = "bat";
56: weight = 2000;
57: request
58: {
59: url = "/node/configuration/hello.js";
60: }
61: }
62: }
settings.ubr
我從別的例子中複製過來並去掉註釋而後進行了一點修改(在測試過程當中修改的):
1: server = "hexpower7";
2: clients = 1;
3: virtualclients = 8;
如今,運行以測試
而後,我以管理者身份運行wcat.bat。你會看到node.exe開始行動。
(記得他們是以SYSTEM運行的,由於我搞不清正確的權限,是個人錯。我總有一天會搞清楚的。)
這是WCAT工具的控制檯輸出。我能夠連續在一秒內作一萬個HelloWorld,這最終會是上百萬個正常請求而且在90秒內獲得迴應。那但是不少個HelloWorld。
記住Hanselman的運行法則。
「什麼都不作,那就有無限的可能」—我
固然,這些都是在一臺配置不錯的機器的本地操做。這不過是個HelloWorld(外加一些日誌),因此沒有太多的測試node和IIS,不過卻是測試了整個系統,IIS,iisnode和node自己的合做互動。
另:ASP.NET IhttpHandler在同臺機器上作一樣的事情,結果是在一秒內有22500個請求,因此node和iisnode還有上升空間,這是個好消息。
如下是node/iisnode的結果:
還有不少東西我能夠配置在兩個站點上,客戶數量,虛擬客戶,還有iisnode特定設置(都在web.config中管理):
1: <configuration>
2: <system.webServer>
3: <handlers>
4: <add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
5: </handlers>
6: <iisnode
7: nodeProcessCommandLine="%systemdrive%\node\node.exe"
8: maxProcessCountPerApplication="4"
9: maxConcurrentRequestsPerProcess="1024"
10: maxPendingRequestsPerApplication="1024"
11: maxNamedPipeConnectionRetry="3"
12: namedPipeConnectionRetryDelay="2000"
13: asyncCompletionThreadCount="4"
14: initialRequestBufferSize="4096"
15: maxRequestBufferSize="65536"
16: uncFileChangesPollingInterval="5000"
17: gracefulShutdownTimeout="60000"
18: loggingEnabled="true"
19: logDirectoryNameSuffix="logs"
20: maxLogFileSizeInKB="128"
21: appendToExistingLog="false"
22: />
23: </system.webServer>
24: </configuration>
至關酷的東西。我很高興能與這個團隊合做,一塊兒致力於讓IIS上的應用性能更好。我很驚訝如今居然能夠不用VM就開始鼓搗node。等我學到更多的東西我還會回來跟你們分享的,不見不散。
相關連接
· GitHub上的iisnode項目
· 下載iisnode二進制文件