精华内容
下载资源
问答
  • 什么是负载均衡 负载平衡(Load balancing)是一种计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免...

    什么是负载均衡

    负载平衡(Load balancing)是一种计算机技术,用来在多个计算机(计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。 使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。负载平衡服务通常是由专用软件和硬件来完成。 主要作用是将大量作业合理地分摊到多个操作单元上进行执行,用于解决互联网架构中的高并发高可用的问题。 - wiki

    负载均衡(Load Balance)是建立在网络协议分层上的,通过网络协议里面的处理将负载的作业合理的分摊到多个操作单元上。

     

     

    所以针对网络协议层有不同负载均衡策略 2/3/4/7层负载均衡 ,负载均衡的实现分 软/硬 ,顾名思义:

    • 一个是通过软件实现,成本低、灵活简单,缺点受服务器性能影响
    • 一个是通过硬件,性能优于软负载均衡,但是成本高

    nodejs能做哪些

    先看下面的请求链路图(举个例子,实现方式、策略、架构等有很多)

     

    1. DNS、VIP、Nginx服务的负载均衡底层服务(云)或者运维已经搭建好了,不需node开发过多关心
    2. Nginx负载均衡到web服务集群,可以使用 upstream 模块配置不同策略
    3. 重点node单个服务负载均衡,主进程分派到多个子进程,这是属于软负载均衡
    4. 假如node服务要通过RPC调用远程其他服务,为了不影响其他服务,需要将RPC均衡分派到其他服务的不同节点上

    结论:从上面看出3、4是nodejs服务可以做的,就是 服务负载均衡 和 rpc负载均衡

    服务负载均衡

    先了解一下nodejs cluster模块,下面是nodejs官方cluster例子代码

    app.js

    const cluster = require('cluster');
    const http = require('http');
    const numCPUs = require('os').cpus().length;
    
    if (cluster.isMaster) {
      console.log(`Master ${process.pid} is running`);
    
      // Fork workers.
      for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
      }
    
      cluster.on('exit', (worker, code, signal) => {
        console.log(`worker ${worker.process.pid} died`);
      });
    } else {
      // Workers can share any TCP connection
      // In this case it is an HTTP server
      http.createServer((req, res) => {
        res.writeHead(200);
        res.end('hello world\n');
      }).listen(8000);
    
      console.log(`Worker ${process.pid} started`);
    }
    
    1. 启动 app.js ,当前执行进程是主线程
    2. 然后会 fork 与cpu个数一样的worker进程
    3. worker进程默认执行 process.argv[1] 文件,即 app.js
    4. 当非 master 进程程启动 http server ,每个worker进程启动一个

    1.如何监听同一个端口

    第一个问题:为什么多个进程server可以监听同一个port?

    The first one (and the default one on all platforms except Windows), is the round-robin approach, where the master process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process. 第一种方法(也是除 Windows 外所有平台的默认方法)是循环法,由主进程负责监听端口,接收新连接后再将连接循环分发给工作进程,在分发中使用了一些内置技巧防止工作进程任务过载。
    The second approach is where the master process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly. 第二种方法是,主进程创建监听 socket 后发送给感兴趣的工作进程,由工作进程负责直接接收连接。
    The second approach should, in theory, give the best performance. In practice however, distribution tends to be very unbalanced due to operating system scheduler vagaries. Loads have been observed where over 70% of all connections ended up in just two processes, out of a total of eight. 理论上第二种方法应该是效率最佳的。 但在实际情况下,由于操作系统调度机制的难以捉摸,会使分发变得不稳定。 可能会出现八个进程中有两个分担了 70% 的负载。

    官方支持2种方法,其实都是主进程负责监听端口,子进程会fork一个handle句柄给主线,通过循环分发或监听发送与worker进程通信,交替处理任务。

    2.进程间如何通信

    第二个问题:进程间如何通信?

    1、主进程和子进程 主进程和子进程通过 IPC 通信

    app.js

    const cluster = require('cluster');
    const http = require('http');
    const numCPUs = require('os').cpus().length;
    
    if (cluster.isMaster) {
      console.log(`Master ${process.pid} is running`);
    
      // Fork workers.
      for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
      }
    
      cluster.on('exit', (worker, code, signal) => {
        console.log(`worker ${worker.process.pid} died`);
      });
    
      cluster.on('listening', (worker) => {
        // send to worker
        worker.send({message: 'from master'})
      });
    
      for (const id in cluster.workers) {
        cluster.workers[id].on('message', (data)=>{
          // receive by the worker
          console.log('master message: ', data)
        });
      }
    
    } else {
      // Workers can share any TCP connection
      // In this case it is an HTTP server
      http.createServer((req, res) => {
        res.writeHead(200);
        res.end('hello world\n');
      }).listen(8000);
    
      console.log(`Worker ${process.pid} started`);
    
      // send to master
      process.send({message: 'from worker'})
    
      process.on('message', (data)=>{
        // receive by the master
        console.log('worker message', data)
      })
    }
    

    这是通过node的原生ipc通信,ipc通信方式有很多种

    • node原先ipc channel
    • shell stdin/stdout
    • socket
    • pipe
    • message queues

    2、子进程与子进程

    • 一对多,可以通过父进程进行分发
    • 一对一,可以通过ipc通信

    3.如何做到进程负载均衡

    第三个问题:如何做到进程负载均衡?

    服务器集群的负载均衡通过上层已经处理了(Nginx、DNS、VIP等),那node服务怎么做的?cluster采用 round-robin 算法策略分发http请求到不同worker进程,关于负载均衡算法下一章《nodejs负载均衡(二):RPC负载均衡》里面会讲

    4.服务异常退出怎么办

    第四个问题:服务异常退出怎么办?

    1. 一般可以通过 try/catch 捕获异常错误,但是node里面如果遗漏异常捕获,可能导致整个进程崩溃
    2. 使用 try/catch 就够了吗?异常会冒泡到 event loop ,触发 uncaughtException 事件,这里可以阻止程序退出
    3. node异常默认情况是打印 stderr 并以代码1退出,触发 exit 事件
    4. 当异常退出时,主线程监听到worker死亡,可以refork一个新的worker
    Tips: 退出的事件还有 Signal Events

    现在来看下 graceful.js 大概实现,在下一节会有完整的代码,完整案例查看graceful-shutdown-example

    'use strict';
    
    module.exports = options => {
      const { processKillTimeout = 3000, server } = options;
    
      let throwErrorTimes = 0
    
      process.on('uncaughtException', function(err) {
        throwErrorTimes += 1;
        console.log('====uncaughtException====');
        console.error(err)
    
        if (throwErrorTimes > 1) {
          return;
        }
    
        close()
      });
    
      function close(){
        server.close(() => {
            // ...do something
        })
      }
    };
    

    5.如何平滑退出

    第五个问题:如何平滑退出?

    在发布时,多台机器分组发布,可以保证服务不会不可访问,但是:

    • 用户正在访问一台下线的服务,如何确保等待用户请求返回在下线?
    • 一个worker服务异常退出,如何平滑重启一个worker?

    一个平滑退出的大概流程:

    1. fork worker
    2. 监听worker状态
    3. worker异常退出refork
    4. 监听master signal退出信号
    5. master退出前kill所有worker
    6. worker退出前close server和worker的子进程
    // master.js
    'use strict';
    
    const cluster = require('cluster');
    const killTree = require('./kill-tree');
    const numCPUs = require('os').cpus().length;
    // const numCPUs = 1;
    
    let stopping = false;
    
    console.log(`Master ${process.pid} is running`);
    
    cluster.setupMaster({
      exec: 'worker.js',
      // silent: true,
    });
    
    // Fork workers.
    for (let i = 0; i < numCPUs; i++) {
      cluster.fork();
    }
    
    cluster.on('fork', worker => {
      worker.on('message', data => {
        // Receive by the worker
        console.log(`${worker.process.pid} master message: `, data);
      });
    });
    
    // Kill all workers
    async function onMasterSignal() {
      if (stopping) return;
      stopping = true;
    
      const killsCall = Object.keys(cluster.workers).map(id => {
        const worker = cluster.workers[id];
    
        return killTree(worker.process.pid);
      });
    
      await Promise.all(killsCall);
    }
    
    // kill(2) Ctrl-C
    // kill(3) Ctrl-\
    // kill(15) default
    // Master exit
    ['SIGINT', 'SIGQUIT', 'SIGTERM'].forEach(signal => {
      process.once(signal, onMasterSignal);
    });
    
    // Terminate the master process
    process.once('exit', () => {
      console.log(`Master about to exit`);
    });
    
    // Worker is listening
    cluster.on('listening', (worker, address) => {
      // Send to worker
      worker.send({ message: 'from master' });
    });
    
    cluster.on('disconnect', worker => {
      console.log(`${worker.id} disconnect`);
    });
    
    // Worker died
    cluster.on('exit', (worker, code, signal) => {
      console.log(
        `Worker ${worker.process.pid} died, code: ${code}, signal: ${signal}`
      );
    
      worker.removeAllListeners();
    
      // killTree(worker.process.pid, function(err) {
      //   console.log(err)
      // });
    
      // stopping server
      if (stopping) return;
    
      console.log('====Refork====');
      // refork a new worker
      cluster.fork();
    });
    
    setTimeout(() => {
      cluster.workers[1].send({
        action: 'throw error',
      });
    }, 600);
    
    // worker.js
    'use strict';
    
    const http = require('http');
    const { fork } = require('child_process');
    const graceful = require('./graceful');
    
    fork('./child');
    
    // Workers can share any TCP connection
    // In this case it is an HTTP server
    const server = http
      .createServer((req, res) => {
        // services excption
        try {
          throw new Error('Happened error');
        } catch (err) {
          res.writeHead(200);
          res.end(`${err.stack.toString()}`);
        }
        // console.log(res)
        // res.setHeader('Content-Type', 'application/json');
        // res.setHeader('Access-Control-Allow-Origin', '*');
        // res.writeHead(200);
        // res.end(JSON.stringify({ success: true }));
      })
      .listen(8000);
    
    graceful({
      server,
    });
    
    // Send to master
    process.send({
      message: 'from worker',
      // server
    });
    
    process.on('message', data => {
      // Receive by the master
      if (data.action && data.action === 'throw error') {
        // The process threw an exception
        throw new Error('Kill myself');
      }
      console.log('Worker message', data);
    });
    

     

    // graceful.js
    'use strict';
    
    const cluster = require('cluster');
    const killTree = require('./kill-tree');
    
    module.exports = options => {
      const { processKillTimeout = 3000, server } = options;
    
      let throwErrorTimes = 0
    
      process.on('SIGTERM', function onSigterm () {
        console.info(`Only graceful shutdown, worker ${process.pid}`)
        close()
      })
    
      process.on('uncaughtException', function(err) {
        throwErrorTimes += 1;
        console.log('====uncaughtException====');
        console.error(err)
    
        if (throwErrorTimes > 1) {
          return;
        }
    
        close()
      });
    
      function close(){
        server.on('request', (req, res) => {
          // closing the http request
          req.shouldKeepAlive = false;
          res.shouldKeepAlive = false;
          if (!res._header) {
            // closing the socket connection
            res.setHeader('Connection', 'close');
          }
        });
    
        if (processKillTimeout) {
          const timer = setTimeout(() => {
            // Kill all child process
            killTree(process.pid,()=>{
              // Worker process to exit
              process.exit(1);
            })
          }, processKillTimeout);
    
          timer.unref && timer.unref();
        }
    
        const worker = cluster.worker;
        if (worker) {
          try {
            server.close(() => {
              try {
                worker.send({ message: 'disconnect' });
                worker.disconnect();
              } catch (err) {
                console.error('Error on worker disconnect');
              }
            });
          } catch (err) {
            console.error('Error on server close');
          }
        }
      }
    };
    

    完整案例查看graceful-shutdown-example

    6.守护进程或主进程挂了怎么办

    第六个问题: 守护进程或主进程挂了怎么办?

    防止出现单点故障,提供主从备份服务器。

    7.主动停止服务

    1. 通过系统命令获取当前node进程信息
    2. 过滤停止脚本进程,获取启动脚本进程
    3. kill master进程,发送 SIGTERM
    4. 主进程监听到 SIGTERM ,开始kill workers,停止server
    // stop.js
    
    const main = async () => {
      const command = isWin
          ? 'wmic Path win32_process Where "Name = \'node.exe\'" Get CommandLine,ProcessId'
          : // command, cmd are alias of args, not POSIX standard, so we use args
            'ps -eo "pid,args" | grep node';
    }
    
    // ...
    main().then((result)=>{
      result.forEach((item)=>{
        process.kill(item.pid, 'SIGTERM')
        // killTree(item.pid)
      });
    })
    
    // master.js
    
    // kill(2) Ctrl-C
    // kill(3) Ctrl-\
    // kill(15) default
    // Master exit
    ['SIGINT', 'SIGQUIT', 'SIGTERM'].forEach(signal => {
      process.once(signal, onMasterSignal);
    });
    

    完整案例查看graceful-shutdown-example,真正要实现一个合理node负载均衡框架,还需要做好 worker 管理及 IPC 通信机制、不同系统兼容性、docker、sticky模式等等

    展开全文
  • 负载均衡可以把用户的请求分摊到多个服务器上进行处理,从而实现了对海量用户的访问支持。负载均衡的架构如图所示: 对于复杂的Web应用来说,用Nginx做前端负载均衡是理所当然的事。 下面,我们用Nginx做NodeJS应用...
  • 用Nginx做NodeJS应用的负载均衡

    万次阅读 2015-01-27 21:34:44
    博客主页:http://blog.csdn.net/chszs负载均衡可以把用户的请求分摊到多个服务器上进行处理,从而实现了对海量用户的访问支持。负载均衡的架构如图所示:对于复杂的Web应用来说,用Nginx做前端负载均衡是理所当然的...

    《用Nginx做NodeJS应用的负载均衡》

    作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs

    负载均衡可以把用户的请求分摊到多个服务器上进行处理,从而实现了对海量用户的访问支持。负载均衡的架构如图所示:


    对于复杂的Web应用来说,用Nginx做前端负载均衡是理所当然的事。

    下面,我们用Nginx做NodeJS应用的负载均衡。

    1、配置Nginx

    修改nginx.conf:

    ....
            upstream sample {
    	      server 127.0.0.1:3000;
    	      server 127.0.0.1:3001;
    	      keepalive 64;
    	    }
             server {
    	        listen 80;
    	        ....
                server_name 127.0.0.1;
    	        ....
                location / {
                   proxy_redirect off;
                   proxy_set_header X-Real-IP $remote_addr;
                   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                   proxy_set_header X-Forwarded-Proto $scheme;
                   proxy_set_header Host $http_host;
                   proxy_set_header X-NginX-Proxy true;
                   proxy_set_header Connection "";
                   proxy_http_version 1.1;
                   proxy_pass http://sample;
               }
            }
    
    这里在3000端口和3001端口各有一个Node.js服务器,这两个服务器在做同样的工作。在upstream节,配置了两个Node.js服务器。此外,我们还设置了proxy_pass http://sample做HTTP请求代理。

    2、构建NodeJS服务器

    var http = require('http');
    var morgan       = require('morgan');
    
    var server1 = http.createServer(function (req, res) {
      console.log("Request for:  " + req.url + "-- port 3000 ");
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('Hello Node.js\n');
    }).listen(3000, "127.0.0.1");
    
    var server2 = http.createServer(function (req, res) {
      console.log("Request for:  " + req.url + "-- port 3001 ");
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('Hello Node.js\n');
    }).listen(3001, "127.0.0.1");
    
    server1.once('listening', function() {
      console.log('Server running at http://127.0.0.1:3000/');
    });
    
    server2.once('listening', function() {
      console.log('Server running at http://127.0.0.1:3001/');
    });
    
    3、访问Nginx服务器

    现在我们可以访问http://127.0.0.1

    可以看到如下的输出:

      Server running at http://127.0.0.1:3000/
      Server running at http://127.0.0.1:3001/
      Request for:  /-- port 3001 
      Request for:  /favicon.ico-- port 3000 
      Request for:  /favicon.ico-- port 3001 
      Request for:  /-- port 3000 
      Request for:  /favicon.ico-- port 3001 
      Request for:  /favicon.ico-- port 3000 
      Request for:  /-- port 3001 
      Request for:  /favicon.ico-- port 3000 
      Request for:  /favicon.ico-- port 3001 
      Request for:  /-- port 3000 
      Request for:  /favicon.ico-- port 3001 
      Request for:  /favicon.ico-- port 3000 
    

    展开全文
  • 主要是关于如何使用nginx做反向代理和负载均衡nodejs多个实例的配置流程,nodejs实例可以是分布在同一台主机上或者不同的主机上的多个实例。 主要内容有 在同一主机创建nodejs多个实例 详细讲解ngnix.conf文件的...

    个人博客: http://zhangsunyucong.top

    前言

    这篇文章适合熟悉nodejs的同学观看。主要是关于如何使用nginx做反向代理和负载均衡nodejs的多个实例的配置流程,nodejs实例可以是分布在同一台主机上或者不同的主机上的多个实例。

    主要内容有

    • 在同一主机创建nodejs多个实例
    • 详细讲解ngnix.conf文件的每项配置的作用

    在同一主机创建nodejs多个实例

    我的nodejs环境:

    • window 7 64位
    • nodejs v8.1.3
    • webstorm 2017版

    根目录/server.js文件

    'use strict';
    
    var express = require('express');
    var timeout = require('connect-timeout');
    var path = require('path');
    var cookieParser = require('cookie-parser');
    var bodyParser = require('body-parser');
    
    var app = express();
    
    // 设置模板引擎,路径在根目录+public中
    app.set('views', path.join(__dirname, 'public'));
    app.set('view engine', 'ejs');
    
    app.use(express.static('public'));
    
    app.use(express.static(path.join(__dirname, 'public')));
    
    // 设置默认超时时间
    app.use(timeout('15s'));
    //请求体
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
    //cookie
    app.use(cookieParser());
    //注册HTTP消息头部信息
    app.use(
        function(req, res, next) {
            res.set(
                {
                    'Content-Type': 'text/html',
                    'Access-Control-Allow-Origin': '*',
                    'Access-Control-Allow-Rememberme': true,
                    'Access-Control-Allow-HttpOnly': false,
                    'Access-Control-Allow-Methods': 'POST, GET, PUT, DELETE, OPTIONS',
                    'Access-Control-Allow-Credentials': true, //false,
                    'Access-Control-Max-Age': '86400', // 24 hours
                    'Access-Control-Allow-Headers': 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
                }
            );
    
            //decodeURI(req.url)
            console.log('%s %s', req.method, req.url);
            next();
        }
    );
    
    //首页
    app.get('/', function(req, res) {
        res.render('index1', { currentTime: new Date() });
    });
    
    app.use(function(req, res, next) {
        // 如果任何一个路由都没有返回响应,则抛出一个 404 异常给后续的异常处理器
        if (!res.headersSent) {
            var err = new Error('Not Found');
            err.status = 404;
            next(err);
        }
    });
    
    // 错误处理
    app.use(function(err, req, res, next) {
        if (req.timedout && req.headers.upgrade === 'websocket') {
            // 忽略 websocket 的超时
            return;
        }
    
        var statusCode = err.status || 500;
        if (statusCode === 500) {
            console.error(err.stack || err);
        }
        if (req.timedout) {
            console.error('请求超时: url=%s, timeout=%d, 请确认方法执行耗时很长,或没有正确的 response 回调。', req.originalUrl, err.timeout);
        }
        res.status(statusCode);
        // 默认不输出异常详情
        var error = {};
        if (app.get('env') === 'development') {
            // 如果是开发环境,则将异常堆栈输出到页面,方便开发调试
            error = err;
        }
        res.render('error', {
            message: err.message,
            error: error
        });
    });
    
    function catchGlobalError(err) {
        // 注册全局未捕获异常处理器
        process.on('uncaughtException', function(err) {
            console.error('Caught exception:', err.stack);
        });
        process.on('unhandledRejection', function(reason, p) {
            console.error('Unhandled Rejection at: Promise ', p, ' reason: ', reason.stack);
        });
    }
    
    //创建两个服务器实体
    var server = require('http').createServer(app);
    var server1 = require('http').createServer(app);
    
    //服务器监听端口
    var PORT = parseInt(process.env.PORT || 3000);
    var PORT1 = PORT + 1;
    
    server.listen(PORT, function (err) {
        console.log('Node app is running on port:', PORT);
        catchGlobalError(err);
    });
    
    server1.listen(PORT1, function (err) {
        console.log('Node app is running on port:', PORT1);
        catchGlobalError(err);
    });
    
    复制代码

    根目录/views/error.ejs

    <!DOCTYPE HTML>
    <html>
      <head>
        <title>Error</title>
        <link rel="stylesheet" href="/stylesheets/style.css">
      </head>
      <body>
        <h1><%= message %></h1>
        <h2><%= error.status %></h2>
        <pre><%= error.stack %></pre>
      </body>
    </html>
    
    复制代码

    根目录/views/index.ejs

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1">
    
      <title>nodejs 和 nginx</title>
        
      <link rel="stylesheet" href="./stylesheets/style.css">
    
    </head>
          <body>
          <p><h3>Hello world</h3></p>
          </body>
    </html>
    
    复制代码

    ngnix配置文件

    nginx.config

    #user  nobody;
    worker_processes  1;
    
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    
    #pid        logs/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
        #                  '$status $body_bytes_sent "$http_referer" '
        #                  '"$http_user_agent" "$http_x_forwarded_for"';
    
        #access_log  logs/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        #keepalive_timeout  0;
        keepalive_timeout  65;
    
        #gzip  on;
    	
    	upstream nodeproxy {
    		server 192.168.10.137:3000 weight=10;       
            server 127.0.0.1:3001 weight=12;   
    	}
    
        server {
            listen       8089;
            server_name  localhost;
    
            #charset koi8-r;
    
            #access_log  logs/host.access.log  main;
    
            location / {
                root   html;
                index  index.html index.htm;
    			proxy_pass  http://nodeproxy; #与upstream的名称一致
    			proxy_redirect  default; 
            }
    
            #error_page  404              /404.html;
    
            # redirect server error pages to the static page /50x.html
            #
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
    
            # proxy the PHP scripts to Apache listening on 127.0.0.1:80
            #
            #location ~ \.php$ {
            #    proxy_pass   http://127.0.0.1;
            #}
    
            # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
            #
            #location ~ \.php$ {
            #    root           html;
            #    fastcgi_pass   127.0.0.1:9000;
            #    fastcgi_index  index.php;
            #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            #    include        fastcgi_params;
            #}
    
            # deny access to .htaccess files, if Apache's document root
            # concurs with nginx's one
            #
            #location ~ /\.ht {
            #    deny  all;
            #}
        }
    
    
        # another virtual host using mix of IP-, name-, and port-based configuration
        #
        #server {
        #    listen       8000;
        #    listen       somename:8080;
        #    server_name  somename  alias  another.alias;
    
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
    
    
        # HTTPS server
        #
        #server {
        #    listen       443 ssl;
        #    server_name  localhost;
    
        #    ssl_certificate      cert.pem;
        #    ssl_certificate_key  cert.key;
    
        #    ssl_session_cache    shared:SSL:1m;
        #    ssl_session_timeout  5m;
    
        #    ssl_ciphers  HIGH:!aNULL:!MD5;
        #    ssl_prefer_server_ciphers  on;
    
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
    
    }
    
    复制代码

    nginx常用命令

    在nginx的安装根目录下,打开命令行工具,运行。

    启动nginx:start nginx 重新加载配置:nginx -s reload 重新打开日志:nginx -s reopen

    关闭nginx: 快速停止:nginx -s stop 有序关闭:nginx -s quit

    如果遇到启动不了nginx,可能是监听的端口被占用。 使用命令:netstat -aon | findstr :80 查询一下

    用浏览器访问localhost:8089,我的测试的结果是:

    "D:\WebStorm 2017.2.1\bin\runnerw.exe" D:\nodejs\node.exe D:\collect\leancloud\jiangebuluo\NodeTestDemo\myServer.js Node app is running on port: 3000 Node app is running on port: 3001 服务器监听的IP: 192.168.10.137 服务器监听的IP: 192.168.10.137 服务器监听的IP: 127.0.0.1 服务器监听的IP: 127.0.0.1 服务器监听的IP: 127.0.0.1 服务器监听的IP: 127.0.0.1 服务器监听的IP: 127.0.0.1 服务器监听的IP: 127.0.0.1 服务器监听的IP: 192.168.10.137 服务器监听的IP: 192.168.10.137


    最后

    另外贴出一个ubuntu的详细配置讲解。来自猎手家园的博客

    #定义Nginx运行的用户和用户组
    user www www;
    
    #nginx进程数,建议设置为等于CPU总核心数。
    worker_processes 8;
     
    #全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
    error_log /usr/local/nginx/logs/error.log info;
    
    #进程pid文件
    pid /usr/local/nginx/logs/nginx.pid;
    
    #指定进程可以打开的最大描述符:数目
    #工作模式与连接数上限
    #这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。
    #现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。
    #这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。
    worker_rlimit_nofile 65535;
    
    
    events
    {
        #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
        #是Linux 2.6以上版本内核中的高性能网络I/O模型,linux建议epoll,如果跑在FreeBSD上面,就用kqueue模型。
        #补充说明:
        #与apache相类,nginx针对不同的操作系统,有不同的事件模型
        #A)标准事件模型
        #Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
        #B)高效事件模型
        #Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。
        #Epoll:使用于Linux内核2.6版本及以后的系统。
        #/dev/poll:使用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
        #Eventport:使用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。
        use epoll;
    
        #单个进程最大连接数(最大连接数=连接数*进程数)
        #根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,理论上每台nginx服务器的最大连接数为。
        worker_connections 65535;
    
        #keepalive超时时间。
        keepalive_timeout 60;
    
        #客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
        #分页大小可以用命令getconf PAGESIZE 取得。
        #[root@web001 ~]# getconf PAGESIZE
        #4096
        #但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
        client_header_buffer_size 4k;
    
        #这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
        open_file_cache max=65535 inactive=60s;
    
        #这个是指多长时间检查一次缓存的有效信息。
        #语法:open_file_cache_valid time 默认值:open_file_cache_valid 60 使用字段:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.
        open_file_cache_valid 80s;
    
        #open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
        #语法:open_file_cache_min_uses number 默认值:open_file_cache_min_uses 1 使用字段:http, server, location  这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cache中总是打开状态.
        open_file_cache_min_uses 1;
        
        #语法:open_file_cache_errors on | off 默认值:open_file_cache_errors off 使用字段:http, server, location 这个指令指定是否在搜索一个文件是记录cache错误.
        open_file_cache_errors on;
    }
     
     
     
    #设定http服务器,利用它的反向代理功能提供负载均衡支持
    http
    {
        #文件扩展名与文件类型映射表
        include mime.types;
    
        #默认文件类型
        default_type application/octet-stream;
    
        #默认编码
        #charset utf-8;
    
        #服务器名字的hash表大小
        #保存服务器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。如果hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。第一次是确定存储单元的地址,第二次是在存储单元中查找键 值。因此,如果Nginx给出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小.
        server_names_hash_bucket_size 128;
    
        #客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
        client_header_buffer_size 32k;
    
        #客户请求头缓冲大小。nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取。
        large_client_header_buffers 4 64k;
    
        #设定通过nginx上传文件的大小
        client_max_body_size 8m;
    
        #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
        #sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
        sendfile on;
    
        #开启目录列表访问,合适下载服务器,默认关闭。
        autoindex on;
    
        #此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
        tcp_nopush on;
         
        tcp_nodelay on;
    
        #长连接超时时间,单位是秒
        keepalive_timeout 120;
    
        #FastCGI相关参数是为了改善网站的性能:减少资源占用,提高访问速度。下面参数看字面意思都能理解。
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 64k;
        fastcgi_buffers 4 64k;
        fastcgi_busy_buffers_size 128k;
        fastcgi_temp_file_write_size 128k;
    
        #gzip模块设置
        gzip on; #开启gzip压缩输出
        gzip_min_length 1k;    #最小压缩文件大小
        gzip_buffers 4 16k;    #压缩缓冲区
        gzip_http_version 1.0;    #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
        gzip_comp_level 2;    #压缩等级
        gzip_types text/plain application/x-javascript text/css application/xml;    #压缩类型,默认就已经包含textml,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
        gzip_vary on;
    
        #开启限制IP连接数的时候需要使用
        #limit_zone crawler $binary_remote_addr 10m;
    
    
    
        #负载均衡配置
        upstream piao.jd.com {
         
            #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
            server 127.0.0.1:3000 weight=3;
            server 127.0.0.1:3001 weight=2;
    
            #nginx的upstream目前支持4种方式的分配
            #1、轮询(默认)
            #每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
            #2、weight
            #指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
            #例如:
            #upstream bakend {
            #    server 192.168.0.14 weight=10;
            #    server 192.168.0.15 weight=10;
            #}
            #2、ip_hash
            #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
            #例如:
            #upstream bakend {
            #    ip_hash;
            #    server 192.168.0.14:88;
            #    server 192.168.0.15:80;
            #}
            #3、fair(第三方)
            #按后端服务器的响应时间来分配请求,响应时间短的优先分配。
            #upstream backend {
            #    server server1;
            #    server server2;
            #    fair;
            #}
            #4、url_hash(第三方)
            #按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
            #例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
            #upstream backend {
            #    server squid1:3128;
            #    server squid2:3128;
            #    hash $request_uri;
            #    hash_method crc32;
            #}
    
            #tips:
            #upstream bakend{#定义负载均衡设备的Ip及设备状态}{
            #    ip_hash;
            #    server 127.0.0.1:9090 down;
            #    server 127.0.0.1:8080 weight=2;
            #    server 127.0.0.1:6060;
            #    server 127.0.0.1:7070 backup;
            #}
            #在需要使用负载均衡的server中增加 proxy_pass http://bakend/;
    
            #每个设备的状态设置为:
            #1.down表示单前的server暂时不参与负载
            #2.weight为weight越大,负载的权重就越大。
            #3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
            #4.fail_timeout:max_fails次失败后,暂停的时间。
            #5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
    
            #nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
            #client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
            #client_body_temp_path设置记录文件的目录 可以设置最多3层目录
            #location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
        }
         
         
         
        #虚拟主机的配置
        server
        {
            #监听端口
            listen 80;
    
            #域名可以有多个,用空格隔开
            server_name www.jd.com jd.com;
            index index.html index.htm index.php;
            root /data/www/jd;
    
            #对******进行负载均衡
            location ~ .*.(php|php5)?$
            {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                include fastcgi.conf;
            }
             
            #图片缓存时间设置
            location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
            {
                expires 10d;
            }
             
            #JS和CSS缓存时间设置
            location ~ .*.(js|css)?$
            {
                expires 1h;
            }
             
            #日志格式设定
            #$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
            #$remote_user:用来记录客户端用户名称;
            #$time_local: 用来记录访问时间与时区;
            #$request: 用来记录请求的url与http协议;
            #$status: 用来记录请求状态;成功是200,
            #$body_bytes_sent :记录发送给客户端文件主体内容大小;
            #$http_referer:用来记录从那个页面链接访问过来的;
            #$http_user_agent:记录客户浏览器的相关信息;
            #通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。
            log_format access '$remote_addr - $remote_user [$time_local] "$request" '
            '$status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" $http_x_forwarded_for';
             
            #定义本虚拟主机的访问日志
            access_log  /usr/local/nginx/logs/host.access.log  main;
            access_log  /usr/local/nginx/logs/host.access.404.log  log404;
             
            #对 "/" 启用反向代理
            location / {
                proxy_pass http://127.0.0.1:88;
                proxy_redirect off;
                proxy_set_header X-Real-IP $remote_addr;
                 
                #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                 
                #以下是一些反向代理的配置,可选。
                proxy_set_header Host $host;
    
                #允许客户端请求的最大单文件字节数
                client_max_body_size 10m;
    
                #缓冲区代理缓冲用户端请求的最大字节数,
                #如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
                #无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误
                client_body_buffer_size 128k;
    
                #表示使nginx阻止HTTP应答代码为400或者更高的应答。
                proxy_intercept_errors on;
    
                #后端服务器连接的超时时间_发起握手等候响应超时时间
                #nginx跟后端服务器连接超时时间(代理连接超时)
                proxy_connect_timeout 90;
    
                #后端服务器数据回传时间(代理发送超时)
                #后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据
                proxy_send_timeout 90;
    
                #连接成功后,后端服务器响应时间(代理接收超时)
                #连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)
                proxy_read_timeout 90;
    
                #设置代理服务器(nginx)保存用户头信息的缓冲区大小
                #设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头,默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小
                proxy_buffer_size 4k;
    
                #proxy_buffers缓冲区,网页平均在32k以下的设置
                #设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k
                proxy_buffers 4 32k;
    
                #高负荷下缓冲大小(proxy_buffers*2)
                proxy_busy_buffers_size 64k;
    
                #设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长
                #设定缓存文件夹大小,大于这个值,将从upstream服务器传
                proxy_temp_file_write_size 64k;
            }
             
             
            #设定查看Nginx状态的地址
            location /NginxStatus {
                stub_status on;
                access_log on;
                auth_basic "NginxStatus";
                auth_basic_user_file confpasswd;
                #htpasswd文件的内容可以用apache提供的htpasswd工具来产生。
            }
             
            #本地动静分离反向代理配置
            #所有jsp的页面均交由tomcat或resin处理
            location ~ .(jsp|jspx|do)?$ {
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://127.0.0.1:8080;
            }
             
            #所有静态文件由nginx直接读取不经过tomcat或resin
            location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|
            pdf|xls|mp3|wma)$
            {
                expires 15d; 
            }
             
            location ~ .*.(js|css)?$
            {
                expires 1h;
            }
        }
    }
    复制代码
    展开全文
  • pm2进程管理多个nodeJs项目介绍

    千次阅读 2018-12-15 10:34:02
    PM2是node进程管理工具,可以利用它来简化很node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单(supervise)。PM2适用于企业级的nodeJS项目,拥有比forever更加完善的功能。 对于nodeJS...

    简介

    PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单(supervise)。PM2适用于企业级的nodeJS项目,拥有比forever更加完善的功能。

    对于nodeJS的话,只做一些简单介绍

    我们知道JavaScript是运行在浏览器中的,浏览器为它提供了一个上下文(context),从而让JavaScript得以解析执行。
    nodeJS其实可以这么理解,它是另外一种上下文,它允许在后端(脱离浏览器环境)解析执行JavaScript代码。因为它使用了Google的V8虚拟机(Google的Chrome浏览器使用的上下文环境),所以代码可以同理德被执行。nodeJS除了可以在浏览器端显示结果之外,还可以直接在控制台输出。

    安装

    在node环境下安装比较简单,嫌慢的话可以考虑(cnpm)

    npm install -g pm2
    

    目录介绍

    pm2安装好后,会自动创建下面目录。

    • $HOME/.pm2 will contain all PM2 related files
    • $HOME/.pm2/logs will contain all applications logs
    • $HOME/.pm2/pids will contain all applications pids
    • $HOME/.pm2/pm2.log PM2 logs
    • $HOME/.pm2/pm2.pid PM2 pid
    • $HOME/.pm2/rpc.sock Socket file for remote commands
    • $HOME/.pm2/pub.sock Socket file for publishable events
    • $HOME/.pm2/conf.js PM2 Configuration

    使用案例

    以nodeJS的框架express来举例
    express项目目录结构

    目录结构介绍
    • bin是项目的启动文件,配置以什么方式启动项目,默认 npm start
    • public是项目的静态文件,放置js css img等文件
    • routes是项目的路由信息文件,控制地址路由
    • views是视图文件,放置模板文件ejs或jade等(其实就相当于html形式文件啦~)
      express这样的MVC框架模式,是一个Web项目的基本构成
    直接输入npm start启动就可以

    在这里插入图片描述

    以上都是准备工作

    PM2管理express项目开始

    一般我们都是通过npm start启动应用,其实就是调用node ./bin/www。那么,换成pm2就是

    	pm2 start ./bin/www --watch
    

    注意,这里用了–watch参数,意味着当你的express应用代码发生变化时,pm2会帮你重启服务。

    官方文档地址:http://pm2.keymetrics.io/docs/usage/quick-start

    常用命令

    启动
    	pm2 start app.js --watch -i 2
    
    参数说明:
    1. –watch:监听应用目录的变化,一旦发生变化,自动重启。如果要精确监听、不见听的目录,最好通过配置文件。
    2. -i --instances:启用多少个实例,可用于负载均衡。如果-i 0或者-i max,则根据当前机器核数确定实例数目。
    3. –ignore-watch:排除监听的目录/文件,可以是特定的文件名,也可以是正则。比如–ignore-watch=“test node_modules “some scripts””
    4. -n --name:应用的名称。查看应用信息的时候可以用到。
    5. -o --output :标准输出日志文件的路径。
    6. -e --error :错误输出日志文件的路径。
    7. –interpreter :the interpreter pm2 should use for executing app (bash, python…)。比如你用的coffee script来编写应用。
    重启
    pm2 restart app.js
    
    停止

    停止特定的应用。可以先通过pm2 list获取应用的名字(–name指定的)或者进程id。

    pm2 stop app_name|app_id
    

    如果要停止所有应用,可以

    pm2 stop all
    

    运行监控的效果
    在这里插入图片描述

    展开全文
  • GRPC 负载均衡实现

    千次阅读 2019-05-12 01:11:33
    导读 gRPC 是google开源的非常优秀的RPC框架,支持PYTHON/...在负载均衡方面不如dubbo的组件那么丰富,但是其提供了服务发现的接口, 可以通过实现其接口,灵活实现负载均衡功能。 下面通过本地配置文件,启动时...
  • nginx负载均衡配置

    2017-05-26 14:50:58
    负载均衡,单从字面上的意思来...由于没有服务器,所以本次测试直接host指定域名,服务器不够,我们用nodejs监听了三端口(8881,8882,8888)来模拟台服务器。nginx监听80端口作为主服务器。 var http = require('h
  • 所谓负载均衡,单从字面上的...由于没有服务器,所以本次测试直接host指定域名,服务器不够,我们用nodejs监听了三端口(8881,8882,8888)来模拟台服务器。nginx监听80端口作为主服务器。 var http = require('htt...
  • 使用node的cluster模块可以监控应用进程,退出后重新启动node应用进程,并可以启动多个node应用进程,做到负载均衡,充分利用资源。 启动单个进程 node bin/www 文件www的内容为: /** * ...
  • 试玩NodeJS多进程

    万次阅读 多人点赞 2018-04-11 16:30:11
    NodeJS的JavaScript运行在单个进程的单个线程上,一JavaScript执行进程只能利用...本文将根据Master-Worker模式,搭建一简单的服务器集群来充分利用多核CPU资源,探索进程间通信、负载均衡、进程重启等知识。 ...
  • 因为负载均衡需要单独的服务器,当然,一服务器也可以,但是就失去了服务器的意义,所以,我还是决定单独创建一基于CentOS 7 的 Nginx 环境镜像   我只需要对我的服务进行一基础负载,之所以选择Nginx,就...
  • #1 开启多个进程,每个进程绑定不同的端口,用反向代理服务器如 Nginx 做负载均衡,好处是我们可以借助强大的 Nginx 做一些过滤检查之类的操作,同时能够实现比较好的均衡策略,但坏处也是显而易见 ---我们引入了一...
  • nodejs之nginx学习

    2019-01-22 15:58:25
    在实际的应用中,你的nodejs项目可能需要部署到台服务器上,nginx为我们提供了服务器解决方案,它可以将请求转发到不同的服务器上。...负载均衡是由台服务器以对称的方式组成一服务器集合...
  • NodeJs 多核多进程并行框架实作 - CNodeNodeJs 多核多进程并行框架实作多核编程的重要性无需多说, 我们直奔主题,目前nodejs 的网络服务器有以下几种支持多进程的方式: #1 开启多个进程,每个进程绑定不同的端口,...
  • TARS快速入门(NodeJs)

    千次阅读 2017-11-17 14:16:41
    个NodeJs应用程序框架需要关注很问题,如自动发布、机部署、负载均衡、监控报警、日志的输出与管理、服务异常重启等等,而Tars应用程序框架就提供了解决这些问题的一整套方案。 Tars是腾讯从2008年到今天一直...
  • nodejs pm2配置使用教程

    2017-08-25 10:26:06
    它基于命令行界面,提供很特性: 内置的负载均衡器等等,下面我们就一起来看看吧。一、简介pm2是一带有负载均衡功能的应用进程管理器,类似有Supervisor,forever。二、安装LinuxBinaries下载地址:...
  • 到各种路由,负载均衡策略;再到故障隔离,熔断等高级功能,已逐渐发展成一高可扩展性,高性能,生产级的RPC框架。 二,模块划分 SOFARPC Node主要包含了四个子模块,分别是: 客户: RPC的客户端实现 服务器: ...
  • PM2 部署 nodejs 项目

    2019-07-26 10:24:49
    forever管理多个站点,每个站点访问量不大,不需要监控。 pm2 网站访问量比较大,需要完整的监控界面。 PM2的主要特性: 内建负载均衡(使用Node cluster 集群模块) 后台运行 0秒停机重载,我理解大概意思是维护...
  • Nodejs— PM2

    2021-02-25 12:22:41
     pm2是一内置负载均衡的node.js应用进程管理器(也支持Windows),其它的类似功能也有不少,但是感觉pm2功能更强,更值的推荐  GitHub地址:https://github.com/Unitech/pm2  API Docs:...
  • 1、forever管理多个站点,每个站点访问量不大,不需要监控。 2、pm2 网站访问量比较大,需要完整的监控界面。 PM2的主要特性: 内建负载均衡(使用Node cluster 集群模块) 后台运行 0秒停机重载,我理解大概意思是...

空空如也

空空如也

1 2 3 4 5
收藏数 91
精华内容 36
关键字:

多个nodejs负载均衡