2013-04-12 165 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