您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
Nginx反向代理Websocket
 
作者 张丹(Conan),火龙果软件    发布于 2014-10-10
  2067  次浏览      17
 

将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

前言

用Nginx给网站做反向代理和负载均衡,是广泛使用的一种Web技术,不仅能够保证后端服务器的隐蔽性,还可以提高网站情况,部署灵活,而且以来源软件实现负载均衡性价比非常高。

不过今天要讲一下,如何用Nginx给Websocket服务器实现反向代理和负载均衡。我也是第一次做这样的尝试,所以仅把功能实现,优化以后再说。

1. 反向代理和负载均衡

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。

负载均衡 (Load Balancing) 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

2. 创建基于Node的websocket服务器端

系统环境:

win7 64bit

npm 1.2.19

node v0.10.5

bower 1.1.2

nginx 1.5.11

redis 2.4.6

创建基于Node的websocket服务器端

新建工程

D:\workspace\javascript>mkdir nginx-websocket && cd nginx-websocket
D:\workspace\javascript\nginx-websocket>npm install socket.io
socket.io@0.9.16 node_modules\socket.io
├── base64id@0.1.0
├── policyfile@0.0.4
├── redis@0.7.3
└── socket.io-client@0.9.16 (xmlhttprequest@1.4.2, uglify-js@1.2.5, active-x-obfuscator@0.0.1, ws@0.4.31)

服务器端启动文件app1.js

~ vi app1.js

var port = 3100;
var io = require('socket.io').listen(port);

io.sockets.on('connection', function (socket) {
    socket.emit('server', {
        server: 'Server1',
        port: port
    });
});

启动程序

node app1.js

3. 创建websocket客户端

通过bower安装socket.io-client库和jquery库

#下载socket.io-client
D:\workspace\javascript\nginx-websocket>bower install socket.io-client
bower socket.io-client#*        cached git://github.com/LearnBoost/socket.io-client.git#0.9.16
bower socket.io-client#*      validate 0.9.16 against git://github.com/LearnBoost/socket.io-client.git#*
bower socket.io-client#~0.9.16 install socket.io-client#0.9.16

socket.io-client#0.9.16 bower_components\socket.io-client

#下载jquery
D:\workspace\javascript\nginx-websocket>bower install jquery
bower jquery#*                  cached git://github.com/jquery/jquery.git#2.1.0
bower jquery#*                validate 2.1.0 against git://github.com/jquery/jquery.git#*
bower jquery#*                     new version for git://github.com/jquery/jquery.git#*
bower jquery#*                 resolve git://github.com/jquery/jquery.git#*
bower jquery#*                download https://github.com/jquery/jquery/archive/2.1.0.tar.gz
bower jquery#*                progress received 0.3MB of 0.7MB downloaded, 46%
bower jquery#*                progress received 0.3MB of 0.7MB downloaded, 50%
bower jquery#*                progress received 0.4MB of 0.7MB downloaded, 56%
bower jquery#*                progress received 0.4MB of 0.7MB downloaded, 61%
bower jquery#*                progress received 0.5MB of 0.7MB downloaded, 67%
bower jquery#*                progress received 0.5MB of 0.7MB downloaded, 72%
bower jquery#*                progress received 0.5MB of 0.7MB downloaded, 77%
bower jquery#*                progress received 0.6MB of 0.7MB downloaded, 81%
bower jquery#*                progress received 0.6MB of 0.7MB downloaded, 86%
bower jquery#*                progress received 0.6MB of 0.7MB downloaded, 91%
bower jquery#*                progress received 0.6MB of 0.7MB downloaded, 94%
bower jquery#*                progress received 0.7MB of 0.7MB downloaded, 99%
bower jquery#*                 extract archive.tar.gz
bower jquery#*                resolved git://github.com/jquery/jquery.git#2.1.0
bower jquery#~2.1.0            install jquery#2.1.0
jquery#2.1.0 bower_components\jquery

创建静态的html文件,作为websocket客户端:client.html

~ vi client.html

<!DOCTYPE html>
<html>
<head>
<title>Websocket Client</title>
<script src="bower_components/socket.io-client/dist/socket.io.min.js"></script>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
</head>
<body>
<h1>Socket.IO Client</h1>
<div id="content">connecting....</div>

<script>
var socket = io.connect('http://localhost:3100');
socket.on('server', function (data) {
console.log(data);
$('#content').html(JSON.stringify(data));
});
</script>

</body>
</html>

用浏览器打开client.html,查看websocket通讯情况。

服务器端和客户端通讯成功。

接下来,我们用Nginx实现Websocket服务器的反向代理。

4. 用Nginx实现反向代理

看文官说明Nginx在1.3以后的版本支持websocket反向代理,但我在Nginx1.4版本测试时失败,nginx1.5.11版本测试成功。

操作步骤:

1). 下载安装Nginx

2). 修改Nginx配置文件,配置反向代理

3). 启动Nginx服务器

4). 修改app1.js,增加超时的设置

5). 修改client.html,修改nginx访问端口

6). 启动Node的Websocket服务器

7). 浏览器访问测试

1). 下载安装Nginx

下载地址:http://nginx.org/en/download.html

2). 修改Nginx配置文件,配置反向代理

修改nginx配置文件:nginx.conf

http {

    // ...省略

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {

	    listen       3102;  #监听3102 
	    server_name localhost;

        location / {
            proxy_pass http://localhost:3100; #代理3100 

            proxy_set_header X-Real-IP $remote_addr;
	    proxy_set_header Host $host;
	    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

	    proxy_http_version 1.1;
	    proxy_set_header Upgrade $http_upgrade;
	    proxy_set_header Connection "upgrade";
        }
    }

    // ...省略
}

设置nginx的访问端口:3102

设置nginx的代理端口:3100

3). 启动Nginx服务器

D:\toolkit\nginx-1.5.11>nginx.exe

4). 修改app1.js,增加超时的设置

修改启动文件:app1.js

var port = 3100;
var io = require('socket.io').listen(port);

io.enable('browser client minification');  // send minified client
io.enable('browser client etag');          // apply etag caching logic based on version number
io.enable('browser client gzip');          // gzip the file
//io.set('log level', 1);                    // reduce logging

io.set('transports', [ 'websocket','flashsocket','htmlfile','xhr-polling','jsonp-polling']);

io.sockets.on('connection', function (socket) {

    socket.emit('server', {
        server: 'Server1',
        port: port
    });
});

5). 修改client.html,修改nginx访问端口

<!DOCTYPE html>
<html>
<head>
<title>Websocket Client</title>
<script src="bower_components/socket.io-client/dist/socket.io.min.js"></script>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
</head>
<body>
<h1>Socket.IO Client</h1>
<div id="content">connecting....</div>

<script>
var socket = io.connect('http://localhost:3102',{ // 访问3102端口
'connect timeout': 500,
'reconnect': true,
'reconnection delay': 500,
'reopen delay': 500,
'max reconnection attempts': 10
});//设置连接超时

socket.on('server', function (data) {
console.log(data);
$('#content').html(JSON.stringify(data));
});
</script>

</body>
</html>

6). 启动Node的Websocket服务器

D:\workspace\javascript\nginx-websocket>node app1.js

7). 浏览器访问测试

打开网页:

这样就打通了nginx反向代理Websocket。不过遇到一个问题,就是tcp建立连接时特别慢,目前还没有好的解决办法。

5. 用Nginx实现多websocket服务器的负载均衡

接下来,我们在Nginx配置负载均衡。

由于基于Socket.io实现的Websocket服务器是单线程的,而访问实例被保存在MemoryStore中。如果我们想实现多个Websocket服务器或多进程调用,那么我们需要把访问实例单独存储,Socket.io集成了通过Redis的NoSQL数据库存储。

socket.io配置说明,可以参考:Configuring Socket.IO

操作步骤:

1). 下载安装Redis服务器并启动

2). 修改app1.js,增加Redis配置

3). 新建app2.js,增加Redis配置

4). 修改Nginx配置文件,配置app1,app2的负载均衡

5). 启动Nginx服务器,启动app1.js, app2.js

6). 浏览器访问测试

1). 下载安装Redis服务器并启动

Redis的window版本的下载地址:https://github.com/rgl/redis/downloads

启动redis

D:\toolkit\Redis>redis-server.exe

2). 修改app1.js,增加Redis配置

修改一个app1.js,绑定Redis存储实例

var port = 3100;
var io = require('socket.io').listen(port);

var RedisStore = require('socket.io/lib/stores/redis')
    , redis  = require('socket.io/node_modules/redis')
    , pub    = redis.createClient()
    , sub    = redis.createClient()
    , client = redis.createClient();

io.set('store', new RedisStore({
    redisPub : pub
    , redisSub : sub
    , redisClient : client
}));

io.enable('browser client minification');  // send minified client
io.enable('browser client etag');          // apply etag caching logic based on version number
io.enable('browser client gzip');          // gzip the file
//io.set('log level', 1);                    // reduce logging

io.set('transports', [ 'websocket','flashsocket','htmlfile','xhr-polling','jsonp-polling']);

io.sockets.on('connection', function (socket) {

    socket.emit('server', {
        server: 'Server1',
        port: port
    });
});

3). 新建app2.js,增加Redis配置

增加一个app2.js,做为第二个websocket服务器

var port = 3101;
var io = require('socket.io').listen(port);

var RedisStore = require('socket.io/lib/stores/redis')
    , redis  = require('socket.io/node_modules/redis')
    , pub    = redis.createClient()
    , sub    = redis.createClient()
    , client = redis.createClient();

io.set('store', new RedisStore({
    redisPub : pub
    , redisSub : sub
    , redisClient : client
}));

io.enable('browser client minification');  // send minified client
io.enable('browser client etag');          // apply etag caching logic based on version number
io.enable('browser client gzip');          // gzip the file
//io.set('log level', 1);                    // reduce logging

io.set('transports', [ 'websocket','flashsocket','htmlfile','xhr-polling','jsonp-polling']);

io.sockets.on('connection', function (socket) {

    socket.emit('server', {
        server: 'Server2',
        port: port
    });
});

4). 修改Nginx配置文件,配置3100,3101端口的负载均衡

修改Nginx配置文件:nginx.conf

http{
	map $http_upgrade $connection_upgrade {
		default upgrade;
		''      close;
	}

	upstream websocket {
		#ip_hash;
		server localhost:3100;  
		server localhost:3101;
	}

	server {
		listen       3102;
		server_name localhost;

		location / {
			proxy_pass http://websocket;
			
			#proxy_pass http://localhost:3100/;  
			
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

			proxy_http_version 1.1;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "upgrade";
		}
	}
}

5). 启动Nginx服务器,启动app1.js, app2.js

D:\toolkit\nginx-1.5.11>nginx.exe
D:\workspace\javascript\nginx-websocket>node app1.js
D:\workspace\javascript\nginx-websocket>node app2.js

6). 浏览器访问测试

打开2个浏览器页面:

这样就实现2个Websocket服务器轮训的负载均衡!!不过,建立连接非常慢的问题依然存在,我还没有什么好的办法。希望了解内情的同学,帮助解答!

 

   
2067 次浏览       17
相关文章 相关文档 相关课程



深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

Android手机开发(一)
理解Javascript
非典型ajax实践
彻底的Ajax
javascript 使用Cookies
使用 jQuery 简化 Ajax 开发
更多...   


Struts+Spring+Hibernate
基于J2EE的Web 2.0应用开发
J2EE设计模式和性能调优
Java EE 5企业级架构设计
Java单元测试方法与技术
Java编程方法与技术


某航空公司IT部 JavaScript实践
某电视软件 HTML5和JavaScript
中航信 JavaScript高级应用开发
大庆油田 web界面Ajax开发技术
和利时 使用AJAX进行WEB应用开发
更多...