https://blog.csdn.net/orangleliu/article/details/50898014
1 思路
client的websocket連接到openresty之后,使用ngx.thread.spawn
啟動兩個 輕線程
,一個用來接收客戶端提交的數據往redis的channel寫,另一個用來訂閱channel,讀取redis的數據寫給客戶端。channel相當于一個chat room,多個client一起訂閱,有人發聊天信息(pub),所有人都能得到信息(sub)。代碼比較簡陋,簡單的思路的實現。
2 服務端代碼
依賴:
- openresty
- redis
- lua-resty-redis
- lua-resty-websocket 只支持RFC 6455
nginx的配置全貼了,就是兩個location,一個是頁面地址,一個是websocket地址。
配置片段
location = /sredis {
content_by_lua_file conf/lua/ws_redis.lua;
}
location ~ /ws/(.*) {
alias conf/html/$1.html;
}
lua代碼
-- simple chat with redis
local server = require "resty.websocket.server"
local redis = require "resty.redis"
local channel_name = "chat"
local msg_id = 0
--create connection
local wb, err = server:new{
timeout = 10000,
max_payload_len = 65535
}
--create success
if not wb then
ngx.log(ngx.ERR, "failed to new websocket: ", err)
return ngx.exit(444)
end
local push = function()
-- --create redis
local red = redis:new()
red:set_timeout(5000) -- 1 sec
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect redis: ", err)
wb:send_close()
return
end
--sub
local res, err = red:subscribe(channel_name)
if not res then
ngx.log(ngx.ERR, "failed to sub redis: ", err)
wb:send_close()
return
end
-- loop : read from redis
while true do
local res, err = red:read_reply()
if res then
local item = res[3]
local bytes, err = wb:send_text(tostring(msg_id).." "..item)
if not bytes then
-- better error handling
ngx.log(ngx.ERR, "failed to send text: ", err)
return ngx.exit(444)
end
msg_id = msg_id + 1
end
end
end
local co = ngx.thread.spawn(push)
--main loop
while true do
-- 獲取數據
local data, typ, err = wb:recv_frame()
-- 如果連接損壞 退出
if wb.fatal then
ngx.log(ngx.ERR, "failed to receive frame: ", err)
return ngx.exit(444)
end
if not data then
local bytes, err = wb:send_ping()
if not bytes then
ngx.log(ngx.ERR, "failed to send ping: ", err)
return ngx.exit(444)
end
ngx.log(ngx.ERR, "send ping: ", data)
elseif typ == "close" then
break
elseif typ == "ping" then
local bytes, err = wb:send_pong()
if not bytes then
ngx.log(ngx.ERR, "failed to send pong: ", err)
return ngx.exit(444)
end
elseif typ == "pong" then
ngx.log(ngx.ERR, "client ponged")
elseif typ == "text" then
--send to redis
local red2 = redis:new()
red2:set_timeout(1000) -- 1 sec
local ok, err = red2:connect("127.0.0.1", 6379)
if not ok then
ngx.log(ngx.ERR, "failed to connect redis: ", err)
break
end
local res, err = red2:publish(channel_name, data)
if not res then
ngx.log(ngx.ERR, "failed to publish redis: ", err)
end
end
end
wb:send_close()
ngx.thread.wait(co)
3 頁面代碼
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<script type="text/javascript">
var ws = null;
function WebSocketConn() {
if (ws != null && ws.readyState == 1) {
log("已經在線");
return
}
if ("WebSocket" in window) {
// Let us open a web socket
ws = new WebSocket("ws://localhost:8008/sredis");
ws.onopen = function() {
log('成功進入聊天室');
};
ws.onmessage = function(event) {
log(event.data)
};
ws.onclose = function() {
// websocket is closed.
log("已經和服務器斷開");
};
ws.onerror = function(event) {
console.log("error " + event.data);
};
} else {
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}
function SendMsg() {
if (ws != null && ws.readyState == 1) {
var msg = document.getElementById('msgtext').value;
ws.send(msg);
} else {
log('請先進入聊天室');
}
}
function WebSocketClose() {
if (ws != null && ws.readyState == 1) {
ws.close();
log("發送斷開服務器請求");
} else {
log("當前沒有連接服務器")
}
}
function log(text) {
var li = document.createElement('li');
li.appendChild(document.createTextNode(text));
document.getElementById('log').appendChild(li);
return false;
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketConn()">進入聊天室</a>
<a href="javascript:WebSocketClose()">離開聊天室</a>
<br>
<br>
<input id="msgtext" type="text">
<br>
<a href="javascript:SendMsg()">發送信息</a>
<br>
<ol id="log"></ol>
</div>
</body>
</html>
4 效果
用iphone試了試,不好使,可能是websocket版本實現的問題。pc端測試可以正常使用。

Reading
posted on 2018-05-04 12:03
思月行云 閱讀(839)
評論(0) 編輯 收藏 引用 所屬分類:
Nginx\Openresty