玩转Nodejs的集群
在Nodejs中使用集群还是不容易的。Javascript的单线程属性让nodejs下的应用很难使用现代机器的多核特性。比如下面的代码实现了一个http服务器的主干部分。这部分代码只会执行在一个线程上,不管这段代码运行的机器是单核的cpu还是1000个内核的cpu。
var http = require("http");
var port = parseInt(process.argv[2]);
http.createServer(function(request, response) {
console.log("Request for: " + request.url);
response.writeHead(200);
response.end("hello world\n");
}).listen(port);
使用多核特性
只需要一点修改,上面的代码就可以把cpu的所有核心都用起来。上面的示例代码将使用cluster模块重构。cluster模块可以让你很容易的创建多个分享端口的进程。每一个进程使用一个系统核心,也就是代码中的numCPUs变量中cpu核心的一个。每一个子进程都实现了HTTP server,并监听指定的端口。
var cluster = require("cluster");
var http = require("http");
var numCPUs = require("os").cpus().length;
var port = parseInt(process.argv[2]);
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on("exit", function(worker, code, signal) {
cluster.fork();
});
} else {
http.createServer(function(request, response) {
console.log("Request for: " + request.url);
response.writeHead(200);
response.end("hello world\n");
}).listen(port);
}
多机器的均衡
使用cluster模块,你就可以更高效的使用硬件。然而,你还是被限制在单一的机器上。如果你的应用有客观的访问量,你最终还是把负载分部在不同的机器上。使用reverse proxy server可以把并发的访问负载到不同的服务器上。
Nodejitsu开发了node-http-proxy模块,一个开源的nodejs应用代理服务。使用以下命令可以安装这个模块:
npm install http-proxy
实际的使用可以参考以下代码。在这里例子中负载被分发到两台服务器上。首先测试反转代理,确保HTTP server运行在8080和8081两个端口上。接下来,运行反转代理,然后用浏览器访问这个代理。如果一切正常的话,你会发现请求被两个服务器交替处理。
var proxyServer = require('http-proxy');
var port = parseInt(process.argv[2]);
var servers = [
{
host: "localhost",
port: 8081
},
{
host: "localhost",
port: 8080
}
];
proxyServer.createServer(function (req, res, proxy) {
var target = servers.shift();
proxy.proxyRequest(req, res, target);
servers.push(target);
}).listen(port);
当然,这个例子只使用了一台机器。然而,如果你有多台机器的话,你可以在一台机器上运行反向代理服务器,其他的机器上运行HTTP server。
使用nginx负载均衡
使用nodejs写的反向代理有一个好处是你使用的技术都是一样的。但是,在生产环境下,更多使用的是nginx来处理负载均衡。nginx是一个开源的HTTP server和反向代理工具,尤其擅长处理静态文件,比如:CSS和HTML。因此,nginx常被用于处理站点的静态文件,和分发动态请求到nodejs的服务器上。
要实现nginx的负载均衡,只需要安装nginx,之后把nodejs服务器作为upstream resource添加在配置文件中。配置文件的路劲一般是{nginx-root}/conf/nginx.conf,{nginx-root}是nginx安装的根目录。整个的配置文件请参考下面的示例。当然,我们只需要用到其中的一小部分。
#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 node_app {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
} server {
listen 80;
server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / {
root html;
index index.html index.htm;
} location /foo {
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://node_app;
} #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;
# server_name localhost; # ssl on;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key; # ssl_session_timeout 5m; # ssl_protocols SSLv2 SSLv3 TLSv1;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on; # location / {
# root html;
# index index.html index.htm;
# }
#} }
如前文所述,本教程只会涉及到整个配置文件的一部分。第一个需要关注的部分如下所示。
upstream node_app {
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
这部分的配置定义了一个upstream服务器,名称为node_app。对这个服务器的请求会分配到就两个ip地址上(这里只用端口区分了一下)。
只是定义了一个upstream服务器还没有告诉nginx如何使用它。因此,我们必须使用如下的指令顶一个路由的规则。使用这个路由,任何的到/foo的请求都会被代理到之前配置的nodejs服务器上。
location /foo {
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://node_app;
}
最后
本教程旨在介绍如何把单线程的Nodejs应用运行在多台机器的多个核心上。你也可以学到如何使用nodejs或者nginx建立一个负载均衡。当然本文不是深入的介绍如何在产品环境下运行的。因此,如果你使用的是nginx,还有很多其他的可以做的,比如缓存,来提高系统性能。你也会需要使用forever,如果崩溃的话这个工具可以重启你的nodejs进程。
玩转Nodejs的集群的更多相关文章
- 玩转nodeJS系列:使用原生API实现简单灵活高效的路由功能(支持nodeJs单机集群),nodeJS本就应该这样轻快
前言: 使用nodeJS原生API实现快速灵活路由,方便与其他库/框架进行整合: 1.原生API,简洁高效的轻度封装,加速路由解析,nodeJS本就应该这样轻快 2.不包含任何第三方库/框架,可以灵活 ...
- 玩转 Redis缓存 集群高可用
转自:https://segmentfault.com/a/1190000008432854 Redis作为主流nosql,在高并发使用场景中都会涉及到集群和高可用的问题,有几种持久化?场景下的缓存策 ...
- Apache+Tomcat +mod_proxy集群负载均衡及session
序言: 在玩Apache+Tomcat +mod_jk集群负载均衡及session的时候发现,还有一种方式可以实现,就是网上各位大牛们说的mod_proxy反向代理. 实在弄的我的知识细胞洋洋.实 ...
- 玩转nodeJS系列:使用cluster创建nodejs单机多核集群(多进程)
前言: nodejs提供了cluster集群(支持端口共享的多进程),cluster基于child_process,process二次封装,方便我们使用该功能实现单机nodejs的web集群. 1.c ...
- 如何创建 Swarm 集群?- 每天5分钟玩转 Docker 容器技术(95)
本节我们将创建三节点的 swarm 集群. swarm-manager 是 manager node,swarm-worker1 和 swarm-worker2 是 worker node. 所有节点 ...
- 5 秒创建 k8s 集群 - 每天5分钟玩转 Docker 容器技术(115)
据说 Google 的数据中心里运行着超过 20 亿个容器,而且 Google 十年前就开始使用容器技术. 最初,Google 开发了一个叫 Borg 的系统(现在命令为 Omega)来调度如此庞大数 ...
- 菜鸟玩云计算之十九:Hadoop 2.5.0 HA 集群安装第2章
菜鸟玩云计算之十九:Hadoop 2.5.0 HA 集群安装第2章 cheungmine, 2014-10-26 在上一章中,我们准备好了计算机和软件.本章开始部署hadoop 高可用集群. 2 部署 ...
- 菜鸟玩云计算之十八:Hadoop 2.5.0 HA 集群安装第1章
菜鸟玩云计算之十八:Hadoop 2.5.0 HA 集群安装第1章 cheungmine, 2014-10-25 0 引言 在生产环境上安装Hadoop高可用集群一直是一个需要极度耐心和体力的细致工作 ...
- Kubernetes 集群日志管理 - 每天5分钟玩转 Docker 容器技术(180)
Kubernetes 开发了一个 Elasticsearch 附加组件来实现集群的日志管理.这是一个 Elasticsearch.Fluentd 和 Kibana 的组合.Elasticsearch ...
随机推荐
- java是如何编码解码的
在上篇博客中LZ阐述了java各个渠道转码的过程,阐述了java在运行过程中那些步骤在进行转码,在这些转码过程中如果一处出现问题就很有可能会产生乱码!下面LZ就讲述java在转码过程中是如何来进行编码 ...
- .net数据库连接防注入参数查询 命令执行 读取 备份 导出导入转化XML格式
ADO.NET是一组类库,让我们通过程序的方式访问数据库.SYSTEM.DATA这个类提供了统一的接口访问Oracle MSSQL Access.像SYSTEM.IO类操作文件一样. **connec ...
- js中函数传参的情况
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 首届阿里巴巴在线技术峰会,9位大V演讲整理!
https://yq.aliyun.com/articles/57826 感谢参加阿里巴巴在线技术峰会.7月19日的3场专家分享:Blink.Docker.电商互动:7月20日的云数据库十大经典案 例 ...
- kegg富集分析之:KEGGREST包(9大功能)
这个包依赖极有可能是这个:https://www.kegg.jp/kegg/docs/keggapi.html ,如果可以看懂会很好理解 由于KEGG数据库分享数据的策略改变,因此KEGG.db包不在 ...
- 每月IT摘录201808--201809
一.技术 海量数据的解决方案: 使用缓存: 页面静态化技术: 数据库优化: 分离数据库中活跃的数据: 批量读取和延迟修改: 读写分离: 使用NoSQL和Hadoop等技术: 分布式部署数据库: 应用服 ...
- 149. Max Points on a Line (Array; Greedy)
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. ...
- 不同的子序列 · Distinct Subsequences
[抄题]: 给出字符串S和字符串T,计算S的不同的子序列中T出现的个数. 子序列字符串是原始字符串通过删除一些(或零个)产生的一个新的字符串,并且对剩下的字符的相对位置没有影响.(比如,“ACE”是“ ...
- access数据库收缩(压缩)
一般是因为表中有大量没用的数据,把没用的数据全部删除 菜单栏的“工具”——“数据库实用工具”——“压缩和修复数据库” OK啦
- vc通过webbrowser操作ie元素
1>需要引用 webbrowser2.h,mshtml.h //m_web绑定的webbrowser的变量 CComQIPtr<IHTMLDocument2,&IID_IHTMLD ...