Nginx担当WebSockets代理

英文原文:http://nginx.com/blog/websocket-nginx/

作者:chszs,转载需注明。

博客主页:http://blog.csdn.net/chszs

WebSocket 协议提供了一种创建支持client和服务端实时双向通信Web应用程序的方法。作为HTML5规范的一部分,WebSockets简化了开发Web实时通信程序的难度。

眼下主流的浏览器都支持WebSockets,包含火狐、IE、Chrome、Safari以及Opera等,并且,越来越多的server应用框架也開始支持WebSockets。

要在企业产品中使用WebSockets,为满足高性能和高可用性,须要多个WebSocketserver。负载均衡层须要支持WebSocket协议。

Nginx从1.3版起就開始支持WebSocket协议,并且能够担当WebSocket应用程序的反向代理以及实现负载均衡。

WebSocket协议和HTTP协议不同,可是WebSocket协议的握手和HTTP是兼容的,它使用HTTP的Upgrade协议头将连接从HTTP连接升级到WebSocket连接。

这个特性使得WebSocket应用程序能够非常easy地应用到现有的基础设施。比如,WebSocket应用能够使用标准的80和443 HTTPport,因此能够通过现有的防火墙设施。

WebSockets应用程序会在client和server之间建立一个长连接,使得开发实时应用非常easy。

HTTP的Upgrade协议头机制用于将连接从HTTP连接升级到WebSocket连接。Upgrade机制使用了Upgrade协议头和Connection协议头。反向代理server在支持WebSocket协议方面面临着一些挑战。挑战之中的一个是WebSocket是一个逐段转发(hop-by-hop)协议。因此当代理server拦截到来自client的Upgrade请求时,代理server须要将自己的Upgrade请求发送给后端server,包含适合的请求头。并且。由于WebSocket连接是长连接,与传统的HTTP端连接截然不同,故反向代理server还须要同意这些连接处于打开(Open)状态,而不能由于其空暇就关闭了连接。

Nginx通过在client和后端server之间建立隧道来支持WebSockets通信。为了让Nginx能够将来自client的Upgrade请求发送到后端server。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做代理的。

此例将使用ws模块,它是基于node.js构建的WebSocket实现。Nginx将担当反向代理server,后端server是一个使用了ws和Node.js的简单WebSockets应用。样例使用的命令在Ubuntu 13.10和CentOS 6.5上測试通过。但对于其它操作系统也许须要稍作改动。

就这个样例来说,WebSocketserver的IP地址是192.168.100.10,Nginxserver的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,我们会为client使用它,可是我们须要创建一个程序来作为我们的server。将以下的代码保存到一个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”,之后监听8010port。等待client的连接。

它会处理收到的全部请求,并且将接收到的消息输出在控制台。之后向client返回一条包含该消息的消息。我们希望Nginx去代理client的请求,能够通过以下的配置实现:

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监听8020port,并把不论什么接收到的请求转发给后端的WebSocketserver。让后端server更好地处理WebSocket协议。

我们能够使用wscat作为client来測试一下:

/root/node_modules/ws/bin/wscat –connect ws://192.168.100.20:8020

上面的命令会通过Nginx反向代理server和后端WebSocketserver建立连接,你能够向server发送随意消息,然后server会返回一条消息。每当你在client发送一条消息,在后端server上能看到该消息的输出,之后在client会显示一条来自服务端的消息。
这是一个交互演示样例:

Server:

Client:

$ node server.js

Server started

wscat –connect ws://192.168.100.20:8020

Connected (press CTRL+C to quit)

> Hello

Received from client: Hello

< Server received from client: Hello

由此我们能够看到client与server能通过Nginx反向代理建立WebSockets通信,并且消息能够持续地进行双向传输。直至client或server断开连接。为了让Nginx能正确处理WebSocket连接,仅仅需正确地设置消息头来处理从HTTP连接升级到WebSocket连接的Upgrade请求。

Nginx担当WebSockets代理的更多相关文章

  1. 使用Nginx做WebSockets代理教程

    WebSocket 协议提供了一种创建支持客户端和服务端实时双向通信Web应用程序的方法.作为HTML5规范的一部分,WebSockets简化了开发Web实时通信程 序的难度.目前主流的浏览器都支持W ...

  2. Nginx 作为 WebSockets 代理

    WebSocket 协议给我们提供了一个创建可以支持客户端和服务端进行双向实时通信的web应用程序的方法.相比之前使用的方法,WebSocket(作为HTML5的一部分)可以使我们更容易开的发出这种类 ...

  3. Windos环境用Nginx配置反向代理和负载均衡

    Windos环境用Nginx配置反向代理和负载均衡 引言:在前后端分离架构下,难免会遇到跨域问题.目前的解决方案大致有JSONP,反向代理,CORS这三种方式.JSONP兼容性良好,最大的缺点是只支持 ...

  4. 在ubuntu上面配置nginx实现反向代理和负载均衡

    上一篇文章(http://www.cnblogs.com/chenxizhang/p/4684260.html),我做了一个实验,就是利用Visual Studio,基于Nancy框架,开发了一个自托 ...

  5. nginx的反向代理和负载均衡的一个总结

    之前一直觉的nginx的反向代理和负载均衡很厉害的样子,最近有机会接触了一下公司的这方面的技术,发现技术就是一张窗户纸呀,捅破了啥都明白了! 接下来先看一下nginx的反向代理: 简单的来说就是ngi ...

  6. nginx做反向代理并防盗链

    nginx做反向代理真的非常简单,只需设置location+proxy_pass即可. 防盗链配置有些复杂,需要注意的地方: 在防盗链的location中需要再设置一下proxy_pass(在这里走了 ...

  7. nginx设置反向代理后,页面上的js css文件无法加载

    问题现象: nginx配置反向代理后,网页可以正常访问,但是页面上的js css文件无法加载,页面样式乱了. (1)nginx配置如下: (2)域名访问:js css文件无法加载: (3)IP访问:j ...

  8. 用nginx做反向代理来访问防外链图片

    用nginx做反向代理来访问防外链图片 女儿的博客从新浪搬到wordpress后,发现原来博客上链接的新浪相册的图片都不能访问了,一年的博客内容,一个个去重新上传图片,修正链接也是个大工程.还是得先想 ...

  9. Nginx 笔记与总结(15)nginx 实现反向代理 ( nginx + apache 动静分离)

    在 nginx 中,proxy 用来实现反向代理,upstream 用来实现负载均衡. 例如有两台服务器,nginx 服务器作为代理服务器,执行 .html 文件,apache 服务器上执行 .php ...

随机推荐

  1. java线程池的初探

    问题来源 发现学习很多技术都提到了线程池的技术,自己的线程池方面没有仔细研究过,现在看了点东西来这里总结下,最近发现写博客是一个很好的锻炼自己并且将学到的东西更加理解的一个方式. 问题探究 java的 ...

  2. 数位dp(D - How Many Zeroes? LightOJ - 1140 )

    题目链接:https://cn.vjudge.net/contest/278036#problem/D 题目大意:T组测试数据,每一次输入两个数,求的是在这个区间里面,有多少个0,比如说19203包括 ...

  3. Servlet笔记8--乱码解决方案

    乱码解决方案: 代码详解: package com.bjpowernode.javaweb.servlet; import java.io.IOException; import javax.serv ...

  4. 解决windows10 里vs2017 直接开始执行提示“此任务要求应用程序有提升的权限”1.

    1.打开vs的安装路径,我的是 C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\ ,找到  VSLauncher.exe 右击该文 ...

  5. springcloud微服务架构搭建:服务调用

    spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign. Ribbon是一个基于HTTP和TCP客户端的负载均衡器,类似nginx反向代理,可 ...

  6. 一步步实现windows版ijkplayer系列文章之一——Windows10平台编译ffmpeg 4.0.2,生成ffplay

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  7. 报错stale element reference: element is not attached to the page document结局方案

    今天在调试脚本时,遇到如下报错: org.openqa.selenium.StaleElementReferenceException: stale element reference: elemen ...

  8. python基础--time和datetime模块

    一:说明在Python中,通常有这几种方式来表示时间:1)时间戳 2)格式化的时间字符串 3)元组(struct_time)共九个元素.由于Python的time模块实现主要调用C库,所以各个平台可能 ...

  9. 虚拟机Failed to start LSB: Bring up/down networking

      1.执行 service network restart 出现以下错误 Restarting network (via systemctl):  Job for network.service f ...

  10. Intellij Idea启用Git可视化界面

    第一步. 第二步. 然后点击OK 验证