Node.js生产部署

时间:2013-04-12 12:14:27

标签: node.js deployment production

这是2013年,自2011年以来发生了很多变化(新的和过时的库),当时回答了大多数流行的node.js部署问题。

我想知道在部署node.js时您认为最佳做法是什么?

如何自动重启node.js app

monit的?

如何创建群集和负载均衡请求(websocket支持)

node-http-proxy,HAProxy?

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

Node.js日志记录实用程序

依旧......

Node.js现在更加成熟,你学到了什么,你推荐什么?

1 个答案:

答案 0 :(得分:3)

部署

我选择部署是通过substack使用fleet

我部署在SmartOS上,让机群集线器和无人机以services运行,并自动重启。

我正在研究dispatcher这是舰队的前端。 Dispatcher允许您将所有存储库保存在github或bitbucket等中心位置,然后从中央git服务器部署最新代码

负载平衡

有关设置http和https服务器的信息,请参阅my answer here。在我的应用程序中,http服务器实际上是另一个节点-http-proxy服务器。在此设置中,我的应用程序可以包含许多使用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 这是由fleet实际产生的节点进程

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