Nginx 作为 WebSockets 代理
WebSocket 协议给我们提供了一个创建可以支持客户端和服务端进行双向实时通信的web应用程序的方法。相比之前使用的方法,WebSocket(作为HTML5的一部分)可以使我们更容易开的发出这种类型的应用程序。绝大多数的现代浏览器都支持WebSocket,包括火狐,IE,Chrome,Safari以及Opera等,同时,越来越多的服务端框架也开始支持WebSocket了。
对于企业应用来说,我们需要多个WebSocket服务器来保障性能和高可用性,因此我们迫切的需要对WebSocket协议进行负载均衡。NGINX自从1.3版本就开始支持WebSocket了,并且可以为WebSocket应用程序做反向代理和负载均衡。
WebSocket 和HTTP协议不同,但是WebSocket中的握手和HTTP中的握手兼容,它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。例如,WebSocket可以使用标准的HTTP端口 80 和 443,因此,现存的防火墙规则也同样适用。
一个WebSockets的应用程序会在客户端和服务端保持一个长时间工作的连接。用来将连接从HTTP升级到WebSocket的HTTP升级机制使用HTTP的Upgrade和Connection协议头。反向代理服务器在支持WebSocket方面面临着一些挑战。一项挑战是WebSocket是一个hop-by-hop协议,所以,当代理服务器拦截到一个客户端发来的Upgrade请求时,它(指服务器)需要将它自己的Upgrade请求发送给后端服务器,也包括合适的请求头。此外,由于WebSocket连接是长时间保持的,所以代理服务器需要允许这些连接处于打开状态,而不是像对待HTTP使用的短连接那样将其关闭。
NGINX 通过在客户端和后端服务器之间建立起一条隧道来支持WebSocket。为了使NGINX可以将来自客户端的Upgrade请求发送给后端服务器,Upgrade和Connection的头信息必须被显式的设置。如下所示:
location /wsapp/ {
proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
一旦我们完成以上设置,NGINX就可以处理WebSocket连接了。
NGINX Websockets 举例
这里有一个展示NGINX如何为WebSocket做代理的实例。这个例子将会使用node.js上的一个实现了WebSocket的模块——ws。这个示例在Ubuntu 13.10 和 CentOS 6.5上测试通过,但对于其他系统来说也许需要稍作修改。就这个例子来说,WebSocket服务器的IP地址是192.168.100.10,NGINX服务器的IP地址是192.168.100.20。如果你还没有安装node.js和npm,你可以通过以下命令安装:
对 Debian/Ubuntu 来说:
sudo apt-get install nodejs npm
对 RHEL/CentOS 来说:
sudo yum install nodejs npm
在Ubuntu上,node.js会被安装为 "nodejs",在CentOS中被会安装为"node"。我们在这例子中统一使用"node",所以,我们将会在Ubuntu上创建一个连接来允许我们使用“node”:
ln -s /usr/bin/nodejs /usr/local/bin/node
然后安装 ws:
sudo npm install ws
注意:如果你得到了一个错误:“Error: failed to fetch from registry: ws” ,那么运行下面的命令应该能解决这个问题:
sudo npm config set registry http://registry.npmjs.org/
接下来,你可以再次运行 sudo npm install ws
ws命令来自/root/node_modules/ws/bin/wscat,我们将会把它当做我们的客户端,但是我们需要创建一个程序来做我们的服务端。将下面的代码保存到一个server.js文件中:
console.log("Server started");
var Msg = '';
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 8010});
wss.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('Received from client: %s', message);
ws.send('Server received from client: ' + message);
});
});
这个程序可以通过下面的命令执行:
node server.js
该程序会输出一条初始化消息“Server started”,之后监听8010端口,等待客户端的连接。它会处理收到的所有请求,并且将接收到的消息输出在控制台,之后向客户端返回一条包含该消息的消息。我们希望NGINX去代理这些请求,通过下面的配置便可实现:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server 192.168.100.10:8010;
}
server {
listen 8020;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
上面的配置会使NGINX监听8020端口,并把接收到的任何请求传递给后端的WebSocket服务器以便恰当的处理WebSocket协议。我们可以使用wscat作为客户端来测试一下:
/root/node_modules/ws/bin/wscat –connect ws://192.168.100.20:8020
上面的命令会通过NGINX代理服务器和WebSocket服务器建立连接,你可以输入你想要发送给服务器的消息,之后服务器会返回一条消息。每当你输入一条消息,你应该可以在服务端看到该消息的输出,之后在客户端会显示一条来自服务端的消息。
这是一个交互示例:
由此我们可以看到服务端与客户端能够通过作为代理的NGINX通信, 而且消息可以持续进行双向传输直到客户端或服务端断开连接。为了能使NGINX正确处理WebSocket, 只需正确地设置消息头来处理更新从http到WebSocket连接的Upgrade请求
。
Nginx 作为 WebSockets 代理的更多相关文章
- Nginx担当WebSockets代理
Nginx担当WebSockets代理 英文原文:http://nginx.com/blog/websocket-nginx/ 作者:chszs,转载需注明. 博客主页:http://blog.csd ...
- 使用Nginx做WebSockets代理教程
WebSocket 协议提供了一种创建支持客户端和服务端实时双向通信Web应用程序的方法.作为HTML5规范的一部分,WebSockets简化了开发Web实时通信程 序的难度.目前主流的浏览器都支持W ...
- Windos环境用Nginx配置反向代理和负载均衡
Windos环境用Nginx配置反向代理和负载均衡 引言:在前后端分离架构下,难免会遇到跨域问题.目前的解决方案大致有JSONP,反向代理,CORS这三种方式.JSONP兼容性良好,最大的缺点是只支持 ...
- 在ubuntu上面配置nginx实现反向代理和负载均衡
上一篇文章(http://www.cnblogs.com/chenxizhang/p/4684260.html),我做了一个实验,就是利用Visual Studio,基于Nancy框架,开发了一个自托 ...
- nginx的反向代理和负载均衡的一个总结
之前一直觉的nginx的反向代理和负载均衡很厉害的样子,最近有机会接触了一下公司的这方面的技术,发现技术就是一张窗户纸呀,捅破了啥都明白了! 接下来先看一下nginx的反向代理: 简单的来说就是ngi ...
- nginx做反向代理并防盗链
nginx做反向代理真的非常简单,只需设置location+proxy_pass即可. 防盗链配置有些复杂,需要注意的地方: 在防盗链的location中需要再设置一下proxy_pass(在这里走了 ...
- nginx设置反向代理后,页面上的js css文件无法加载
问题现象: nginx配置反向代理后,网页可以正常访问,但是页面上的js css文件无法加载,页面样式乱了. (1)nginx配置如下: (2)域名访问:js css文件无法加载: (3)IP访问:j ...
- 用nginx做反向代理来访问防外链图片
用nginx做反向代理来访问防外链图片 女儿的博客从新浪搬到wordpress后,发现原来博客上链接的新浪相册的图片都不能访问了,一年的博客内容,一个个去重新上传图片,修正链接也是个大工程.还是得先想 ...
- Nginx 笔记与总结(15)nginx 实现反向代理 ( nginx + apache 动静分离)
在 nginx 中,proxy 用来实现反向代理,upstream 用来实现负载均衡. 例如有两台服务器,nginx 服务器作为代理服务器,执行 .html 文件,apache 服务器上执行 .php ...
随机推荐
- MYSQL连接字符串参数解析(解释)
被迫转到MySQL数据库,发现读取数据库时,tinyint类型的值都被转化为boolean了,这样大于1的值都丢失,变成true了.查阅资料MySQL中无Boolean类型,都是存储为tinyint了 ...
- Hibernate生成数据库表
首先创建实体类 import java.util.Date; public class ProductionEntity { public Integer getId() { return id; } ...
- linux创建日期文件名
linux创建文件名添加当前系统日期时间的方法 使用`date +%y%m%d` Example: mkdir `date +%y%m%d` tar cfvz /tmp/bak.`date +%y%m ...
- Java 线程--继承java.lang.Thread类实现线程
现实生活中的很多事情是同时进行的,Java中为了模拟这种状态,引入了线程机制.先来看线程的基本概念. 线程是指进程中的一个执行场景,也就是执行流程,进程和线程的区别: 1.每个进程是一个应用程序,都有 ...
- flask之wtforms 表单验证(一)
一 安装wtforms pip install wtforms 二 导入相关模块及对象 from wtforms import Form, widgets, validators from wtf ...
- Java多线程系列--CopyOnWriteArraySet
转载:http://www.cnblogs.com/skywang12345/p/3498497.html 概要 本章是JUC系列中的CopyOnWriteArraySet篇.接下来,会先对CopyO ...
- PAT 1061. Dating
题是别人出的,不按她的想法来也没办法,真心想k一顿 #include <cstdio> #include <cstdlib> using namespace std; cons ...
- 11.6NOIP模拟赛解题报告
心路历程 预计得分:\(100 + 100 + 100 = 300\) 实际得分:\(100 +100 +100 = 300\) 学OI两年终于AK了一次qwq(虽然题目炒鸡水..) 纪念一下这令人激 ...
- JavaScript 二维数组排列组合
<html> <head> <title>二维数组排列组合</title> </head> <body> <div id= ...
- 拖动条SeekBar
1TextView tv=(TextView)findViewById(R.id.TV); 2 tv.setMovementMethod(ScrollingMovementMethod.getInst ...