2013-04-12 164 views
3

2013年,自2011年以來發生了很大變化(新的&過時的庫),當時最受歡迎的node.js部署問題得到解答。Node.js生產部署

我想知道您在部署node.js時如何考慮最佳實踐。

如何自動重新啓動的Node.js應用

monit的?

如何創建一個集羣和負載均衡請求(WebSocket的支持)

節點HTTP代理,HAProxy的?

hook.io已被刪除,因此我不太喜歡使用node-http-proxy。

Node.js的記錄工具

等等...

Node.js的是更成熟了,你學到了什麼,你有什麼建議?

+0

爲什麼downvote?很多改變,例如'羣集(https://github.com/learnboost/cluster)'不支持新的node.js,hook.io不再存在,... – Ben

+0

downvotes是_question_,它不適合堆棧溢出(有關更多信息,請參閱[FAQ](http://stackoverflow.com/faq))。我懷疑任何人downvoted不同意node.js在過去的2年裏已經改變 – Clive

+0

我應該在哪裏問這個? – Ben

回答

3

部署

我的部署選擇是使用由fleet亞組

我上部署SmartOS並有車隊樞紐運行爲services無人機自動獲得重新啓動。

我正在致力於dispatcher,這是一個車隊的前端。調度程序將允許你把你所有的回購在一個集中的地方,如github上或到位桶,然後從中央的Git服務器部署最新的代碼

負載平衡

用於設置一個HTTP和HTTPS服務器見my answer here 。在我的應用程序中,http服務器實際上是另一個節點-http代理服務器。在此設置我的應用程序可以由那些與seaport

路由HTTP服務器註冊

var http = require('http') 
var https = require('https') 
var httpProxy = require('http-proxy'); 
var seaport = require('seaport'); 
var fs = require('fs') 
var inspect = require('eyespect').inspector(); 
var express = require('express') 
function router(data, cb) { 
    var app = express() 
    var config = data.config 
    var logger = data.logger 
    var appPort = config.get('application:port'); 
    var routerConfig = config.get('router') 
    var seaHost = config.get('seaport:host') 
    var seaPort = config.get('seaport:port') 
    var ports = seaport.connect(seaPort, seaHost) 
    var proxy = new httpProxy.RoutingProxy(); 
    app.use(express.methodOverride()); 
    app.use(app.router) 
    var server = http.createServer(app) 
    app.all('/api/:service/*', function (req, res) { 
    var service = req.params.service 
    var ps = ports.query(service); 
    if (!ps || ps.length === 0) { 
     ps = null 
     unavailable(req, res, service, logger); 
     service = null 
     return 
    } 
    var item = ps[0] 
    // remove /api/service/ from start of the url 
    var newURL = req.url.replace(/^\/api\/.*?\//, '/') 
    logger.debug('proxying to api service', { 
     role: router, 
     service: service, 
     url: req.url, 
     newURL: newURL 
    }) 
    req.url = newURL 
    proxy.proxyRequest(req, res, { 
     host: item.host, 
     port: item.port 
    }); 
    item = null 
    }) 

    var pong = 'PONG' 
    app.get('/ping', function (req, res) { 
    res.send(pong) 
    }) 
    app.get('/services', function (req, res) { 
    return showServices(req, res, ports) 
    }) 
    app.all('/*', function (req, res) { 
    var service = 'web' 
    var ps = ports.query(service); 
    if (!ps || ps.length === 0) { 
     unavailable(req, res, service, logger); 
     service = null 
     ps = null 
     return 
    } 

    proxy.proxyRequest(req, res, { 
     host: ps[0].host, 
     port: ps[0].port 
    }); 
    ps = null 
    }) 

    var serverPort = routerConfig.port 
    server.listen(serverPort, function (err, reply) { 
    if (err) { return cb(err); } 
    logger.debug('router application online', { 
     type: 'router', 
     port: serverPort 
    }); 
    var output = { 
     port: serverPort, 
     server: server 
    } 
    cb(null, output) 
    }); 
} 
function showServices(req, res, ports) { 
    var ps = ports.query(); 
    var data = { 
    message: 'Current services registered', 
    services: ps 
    } 
    res.writeHead(200) 
    return res.end(JSON.stringify(data)) 
} 

function isServicesURL(url) { 
    var pattern = /^\/services/i; 
    return pattern.test(url) 
} 

function unavailable(req, res, service, logger) { 
    var resData = { 
    error: 'service unavailable', 
    message: 'no servers are available to serve your request', 
    url: req.url, 
    role: 'router' 
    service: service 
    }; 
    logger.debug('router service unavailable', { 
    role: 'router', 
    responseData: resData 
    }) 
    res.writeHead(500); 
    return res.end(JSON.stringify(resData)); 
} 

module.exports = router; 

spinUpRouter.js這是實際上是由車隊

催生了節點過程中的許多小型服務
var inspect = require('eyespect').inspector() 
var assert = require('assert') 
var fs = require('fs') 
var routerLib = require('./index.js'); 
var optimist = require('optimist'); 
var nconf = require('nconf') 
var argv = optimist.demand(['config']).argv; 
var configFilePath = argv.config 
assert.ok(fs.existsSync(configFilePath), 'config file not found at path: ' + configFilePath); 
var config = nconf.argv().env().file({file: configFilePath}); 
var logger = require('loggly-console-logger') 
var routerData = { 
    config: config, 
    logger: logger 
} 
logger.debug('spinning up router', { 
    type: 'router', 
    configFilePath: configFilePath 
}) 
routerLib(routerData, function (err, server) { 
    inspect('router online') 
}) 

伐木

我使用winston來管理我的日誌。更具體地說,我使用控制檯和Loggly傳輸。我這麼做,我已經把它包裝成一個模塊loggly-console-logger