Express 开发与部署最佳实践

本篇文章翻译自expressjs官方网站,源地址如下:express最佳实践 ,分别从dev角度和ops角度讨论了如何提升express应用的运行性能以及部署的最佳方式。

针对开发者需要注意的问题

对于一个express应用我们,一般有以下的几种方法来提升应用的运行效率以及响应率。

  1. 使用gzip压缩
  2. 代码中不要使用同步函数
  3. 使用中间件处理静态文件
  4. 合理的日志处理方法
  5. 正确的处理异常

以下我们将分别对于每个子项目进行展开分析。

1.使用gzip压缩

使用gzip压缩可以显著的减小响应包的大小,这样就提升了客户端的响应速度,我们可以通过使用compression中间件来处理gzip的压缩。对于一个大量用户的网站,最佳的方式是在反向代理端设置压缩方式。可以参考我的另一篇文章专门介绍如何配置nginx来处理压缩和静态文件的。这样的话,我们在代码端就不用再调用compression中间件了,nginx会帮助我们完成此项工作。

var compression = require(‘compression‘);
var express = require(‘express‘);
var app = express();
app.use(compression());

  

2.不要使用同步函数

我们知道node主进程为一个单一线程的程序(异步处理为多线程)。主线程中如果我们调用一些同步函数,而且这些同步函数执行时间较长,则会影响后续程序的执行等待时间。针对web端则表现为其他用户的访问延迟增大。所以在生产环境中,即便一个返回几个微妙的程序,对于大量用户的访问都将会造成积累效应。所以尽量使用异步的方式去编写代码。

如果使用Node.js 4.0+ 或者 io.js 2.1.0+,可以使用参数 --trace-sync-io 去打印针对同步函数的告警信息。

3.使用中间件来处理静态文件

我们有时候调用res.sendFile()来处理静态文件,但是不要在生产环境中使用,这样会针对每个请求都去读该文件,不仅没有效率而且影响整体的性能,可以通过使用serve-static中间件来处理文件,但是我们推荐的更好的方式是使用nginx等反向代理静态文件。

4.合理的日志处理方式

我们在开发环境中有时候会通过console.log或者console.err标记一些点或者调试输出内容.但是这些函数都是同步的,将输出内容输出到终端与输出到文件的道理是相同,所以在生产环境中不要这样做。除非不得已去讲输出传递到另一个程序中的时候。我们可以使用debug模块来实现输出,该模块将判断环境变量是否是开发环境,执行debug输出,保证你的程序的异步处理。对于记录日志的话,大家可以参考一篇针对日志系统的比较文章比较Winston和Bunyan

5. 正确的处理异常

首先对于node程序来说,一旦遇到不可处理的异常,则整个进程就会down掉,如果我们配置了pm2或者forever这样的进程管理工具的话,他会帮助我们去处理我们的程序失败自启动。

对于代码中异常的处理我们一般的使用方法:

  1. 使用try-catch
  2. 使用promises

这里有一篇文章比较详细的介绍了如何构建健壮的程序来处理错误异常,供参考链接地址

不要使用uncaughtException来处理所有的异常,虽然一定程度上可以导致你的程序不中断,但是程序将包含不稳定的代码持续的运行下去,这样的代码运行在线上可能造成的后果更加的严重,甚至有过建议将该错误处理方式移除node内核。

也不要使用domains来处理错误,该模块已被标记为待移除模块。

使用try-catch是一种比较简单的错误处理方式,比如下面的代码:

app.get(‘/search‘, function (req, res) {
 // Simulating async operation
 setImmediate(function () {
   var jsonStr = req.query.params;
   try {
     var jsonObj = JSON.parse(jsonStr);
     res.send(‘Success‘);
   } catch (e) {
     res.status(400).send(‘Invalid JSON string‘);
   }
 });
});

  

但是我们知道try-catch只能应用在同步的代码上面,对于异步的代码处理我们无法使用该方式进行处理。对于异步代码的异常处理我们可以使用promises来完成。只需要增加一个catch()方法就可以捕获流程中的整个代码块的异常。

app.get(‘/‘, function (req, res, next) {
  // do some sync stuff
  queryDb()
    .then(function (data) {
      // handle data
      return makeCsv(data)
    })
    .then(function (csv) {
      // handle csv
    })
    .catch(next);
});

app.use(function (err, req, res, next) {
  // handle error
});

  

当然了,我们需要在每个代码块中都加入promises返回。更多的信息可以参考一下链接Asynchronous Error Handling in Express with Promises, Generators and ES7

生产环境安装部署

以下我们讨论的是针对生产环境中express应用安装部署上需要注意的问题。

  1. 设置NODE_ENV为“production”
  2. 确保应用的自动重启
  3. 将应用部署一个集群中
  4. 缓存请求结果
  5. 使用负载均衡
  6. 使用反向代理
1. 设置运行环境变量

一般我们设置node环境变量有两种,分别是 development 和 production。设置环境变量为production将会使得express应用

  1. 缓存视图模板
  2. 缓存css文件
  3. 生成更少的冗余错误信息

另外如果大家感兴趣的话可以查看这篇文章环境变量测试,这里作者对于设置该变量前后做了一些性能上的对比,非常详细。

如果我们使用upstart来管理应用的话我们需要配置文件中加入环境变量

# /etc/init/env.conf
env NODE_ENV=production

  

如果是使用systemd来管理的话,则修改配置文件如下:

# /etc/systemd/system/myservice.service
Environment=NODE_ENV=production

  

2.确保自启动

这里自启动不仅仅指的是如何在程序异常终止之后启动而且还要保证程序在操作系统重启之后能自启动。这里我们分别介绍下两种情况。

  1. 使用一个进程管理器

进程管理器一般可以帮助我们,获得进程的运行性能和资源的消耗,动态的修改配置提升性能,集群控制。这里我么推荐的一般可以使用strongloop process manager或者pm2还有forever,同样详细的参考如下链接进程管理器比较 通过上述的比较我们可以看出,strongloop的进程管理器支持的特性更丰富一些,特别是查看cpu占用堆占用,集成操作系统脚本,远程管理集群等等。

  1. 随系统启动的程序自启动

随系统启动的程序,我们可以使用之前的进程管理器,forever应该是不支持的。其他的都可以生成对应的启动脚本,当操作系统启动的时候,进程管理器启动,并带动程序的启动。或者我们可以直接配置使用systemd等方式来管理进程的开机启动。 我们这里简单的通过介绍systemd的方式来介绍如何设置程序的随系统启动。systemd是一个linux系统的服务管理器。一个systemd的配置文件被称作为unit file.以.service为后缀。

[Unit]
Description=Awesome Express App

[Service]
Type=simple
ExecStart=/usr/local/bin/node /projects/myapp/index.js
WorkingDirectory=/projects/myapp

User=nobody
Group=nogroup

# Environment variables:
Environment=NODE_ENV=production

# Allow many incoming connections
LimitNOFILE=infinity

# Allow core dumps for debugging
LimitCORE=infinity

StandardInput=null
StandardOutput=syslog
StandardError=syslog
Restart=always

[Install]
WantedBy=multi-user.target

  

3. 将app运行在一个集群中

在多核心处理上运行的应用,可以通过使用cluster模块启动多个实例运行在不同的处理器上。并在多个实例上实现“负载均衡”。 但是对于不同的实例,由于内存空间的隔离,导致所有的程序对象都是本地的,无法实现共享,但是我们可以借助于redis这样的工具实现对象的共享。并且对于某个进程的终端不会影响其他进程的处理,只需要在编写代码的时候记录此次终端并生成一个新的实例即可。

我们可以使用node的cluster模块(需要编写代码实现)或者是strongloop的进程管理器来处理,并且不需要修改代码。strongloop PM将根据cpu的数目自动的生成多个进程,并且可以手动调整该值。

4. 缓存请求

使用缓存,可以极大的提升响应速度,而不需要对于重复的请求做重复的操作。我们可以使用nginx缓存配置来配置缓存

5. 使用负载均衡

单一的express进程服务,不管如何优化都无法达到一个很高的性能需求,特别是对于一个拥有很多用户的web应用。我们可以通过使用一个负载均衡器来完成应用的水平的扩展。比如使用nginx或者HAProxy来完成负载均衡。在使用负载均衡的时候,我们可能需要确保每一个请求关联相对应的会话ID落到同一个进程上。这里有一篇文章可以供参考,了解如何配置负载均衡socket.io配置负载均衡

另外strongloop pm可以很好的与nginx配合设置负载均衡。

6. 反向代理服务

反向代理服务器一般设置在请求入口处,完成错误页面处理,压缩处理,缓存和静态文件处理,负载均衡操作等等。具体的可参考nginx或者HAProxy的配置来完成反向代理服务的搭建。

时间: 2024-11-05 13:31:09

Express 开发与部署最佳实践的相关文章

Express 开发与部署最佳实践 -- 待续

链接 nginx 代理缓存  压缩 等 全部采用异步 使用try catch  处理同步异常  promise 处理异步 异常,  而不是使用 domains  或者 uncaughtException

Cobbler自动化部署最佳实践

第1章 Cobbler自动化部署最佳实践 运维自动化在生产环境中占据着举足轻重的地位,尤其是面对几百台,几千台甚至几万台的服务器时,仅仅是安装操作系统,如果不通过自动化来完成,根本是不可想象的. 面对生产环境中不同服务器的需求,该如何实现批量部署多版本的操作系统呢?Cobbler便可以的满足这一实际需求,实现多版本操作系统批量部署. 笔者QQ:572891887 Linux架构交流群:471443208 1.1 Cobbler简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整

SharePoint开发中的最佳实践(再续)

SharePoint开发中的最佳实践 20.SPViewScope介绍 Default :仅显示指定文件夹下的文件和子文件夹 FilesOnly:仅显示指定文件夹下的文件 Recursive:显示所有文件夹下的文件 RecursiveAll:显示所有文件夹下的所有文件和子文件夹 以上这个属性使用在CAML中,用于控制在哪些范围内进行查找,我们可以根据实际的查找需求,对这个ViewAttribute属性进行设置,来完成我们的操作. 21.SPGridView介绍 SPGridView在GridVi

SSL/TLS部署最佳实践

原文: https://www.ssllabs.com/downloads/SSL_TLS_Deployment_Best_Practices_1.3.pdf 译者: Shawn the R0ck,(后面校正的自己加到后面) SSL/TLS部署最佳实践 作者:Ivan Risti? version 1.3 (17 September 2013) Copyright ? 2012-2013 Qualys SSL Labs 抽象: SSL/TLS是一个看似简单的技术.非常容易部署和让她跑起来,但是.

Typescript 开发环境的最佳实践

Typescript 开发环境的最佳实践 0?? git init(略) 1???? 初始化:$ yarn add -D ts-node typescript 2?? 生成 tsconfig.json:$ yarn tsc -init 3?? 配置 TSLint:$ yarn add tslint -D 4?? 生成 tslint.json:$ yarn tslint --init 5?? 创建 src/index.ts:$ mkdir src && echo "console.

彼之蜜糖,吾之砒霜——聊聊软件开发中的最佳实践

"描述一个事物,唯有一个名词定义它的概念,唯有一个动词揭露它的行为,唯有一个形容词表现它的特征.要做的,就是用心去寻找那个名词.那个动词.那个形容词--" -- 福楼拜 (Gustave Flaubert) 我想讲个故事. 很久很久以前(一般讲故事都是这样开头吧), 两个老工程师在一起聊天,谈各自生涯中最自豪的工程.其中一个先讲述了他的杰作: " 我们建造的桥,横跨一个峡谷,峡谷很宽很深.我们花了两年时间研究地质,选择材料.聘请了最好的工程师团队来设计方案,而这又花了五年时间

MVP模式在Android开发中的最佳实践

这篇文章拖了好久了,一直存在草稿箱里没有继续写,趁今天有空,撸撸完. 回想一下,你刚刚学习Android的时候,总会看到一些书上写着,Android使用的是MVC模式,Activity就是一个Controller,或许那个时候,你没有什么深刻的体会.随着经验的积累.你发现,Activity既是Controller,掌管着许许多多的业务逻辑,同时它也作为View的一部分,控制着视图层的显示.久而久之,这个Controller便显得过于重,职责不再那么单一. 于是,再后来,为了使Activity的职

Zabbix3.0安装部署最佳实践

Zabbix介绍 1.1zabbix 简介 Zabbix 是一个高度集成的网络监控解决方案,可以提供企业级的开源分布式监控解决方案,由一个国外的团队持续维护更新,软件可以自由下载使用,运作团队靠提供收费的技术支持赢利 zabbix是一个基于Web界面的,提供分布式系统监控以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营,并提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题 zabbix主要由2部分构成zabbix server和zabb

python开发利器ulipad最佳实践

介绍 UliPad是一个国人开发的python轻量级编辑器,导向和灵活的编程器.它如类浏览器,代码自动完成许多功能,如:HTML查看器,目录浏览器,向导等. 下载与安装 下载地址:https://pypi.python.org/pypi/UliPad 安装,傻瓜式,一路next即可 配置 安装好之后双击启动之后逐步进行下面的配置. 1.文件>目录浏览,这样我们可以在左侧看到目录方便管理脚本,最终效果图如下: 2.编辑>参数>python>设置python解释器>增加>选