3

现在是 2013 年,自 2011 年(新的和过时的库)以来发生了很多变化,当时最流行的 node.js 部署问题得到了解答。

我想知道您在部署 node.js 时认为最佳实践是什么。

如何自动重启 node.js 应用程序

监视?

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

节点http代理,HAProxy?

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

Node.js 日志记录实用程序

等等...

Node.js 现在成熟了很多,你学到了什么,你有什么推荐的?

4

1 回答 1

3

部署

我的部署选择是按子堆栈使用舰队

我部署在 SmartOS 上,并让舰队中心和无人机作为服务运行,这些服务会自动重启。

我正在开发调度程序,它是车队的前端。Dispatcher 将允许您将所有存储库保存在中央位置,例如 github 或 bitbucket,然后从中央 git 服务器部署最新代码

负载均衡

有关设置 http 和 https 服务器的信息,请在此处查看我的答案。在我的应用程序中,http 服务器实际上是另一个 node-http-proxy 服务器。在这个设置中,我的应用程序可以包含许多在海港注册的小服务

路由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

于 2013-04-12T13:23:55.610 回答