青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Fork me on GitHub
隨筆 - 215  文章 - 13  trackbacks - 0
<2018年5月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789


專注即時通訊及網游服務端編程
------------------------------------
Openresty 官方模塊
Openresty 標準模塊(Opm)
Openresty 三方模塊
------------------------------------
本博收藏大部分文章為轉載,并在文章開頭給出了原文出處,如有再轉,敬請保留相關信息,這是大家對原創作者勞動成果的自覺尊重??!如為您帶來不便,請于本博下留言,謝謝配合。

常用鏈接

留言簿(1)

隨筆分類

隨筆檔案

相冊

Awesome

Blog

Book

GitHub

Link

搜索

  •  

積分與排名

  • 積分 - 221316
  • 排名 - 117

最新評論

閱讀排行榜

  • https://www.aliyun.com/jiaocheng/647017.html
    https://github.com/chenxiaofa/p
    前言

    作為一個游戲從業者不可能不使用推方案,以前一直使用 nginx-push-stream-module這個模塊的 Forever Iframe模式來實現推方案。

    最近決定研究下 lua-resty-websocket來實現一個更加高效好用推方案

    不推薦使用的場景

    由于 OpenResty目前還不能做到跨 worker通信,所以想到實現指定推送需要中轉一次,效率上可能不如其他語言如 golang等

    過于復雜的業務邏輯 頻繁的指定推送(單對單、組、Tag等) 廣播過多 一起工作的好基友們

    想要推的優雅以下幾個基友的幫忙是不可或缺的

    ngx.semaphore

    它可以讓你在想要發消息的地方優雅的進入到發送階段,也可以讓你來優雅的控制一個鏈接超時的關閉。

    ngx.shared

    由于目前我們無法做到跨 worker的通信,所以必須借助共享內存來中轉不屬于當前 worker的消息。

    lua-resty-websocket

    由于貪圖方便還是直接使用了現成的庫,喜歡折騰的小伙伴請移步 stream-lua-nginx-module

    大概的思路

    由于不能跨 worker通信所以我給每個 worker申請了一個 shared共享內存來保存消息。

    理論上 shared的數量等于 worker的數量最佳。

    然后每個 worker啟動一個 timer來判斷當前 worker的 message id和 shared中的 message id是否有變化。

    這里為什么不用 shared的有序列表來做,容我先賣個關子。

    當發生變化時,判斷消息的目標是否在自己的 session hash中,如果在則發之。

    開始準備工作 修改配置文件

    首先修改 nginx.conf配置,增加以下設置

    lua_shared_dict message_1 10m;
    lua_shared_dict message_2 10m;
    lua_shared_dict message_n 10m;
    init_worker_by_lua_file scripts/init_worker_by_lua.lua;
    init_worker_by_lua
    local ngx = ngx
    local ngx_log = ngx.log
    local ngx_ERR = ngx.ERR
    local ngx_timer_at = ngx.timer.at
    local require = require
    local socketMgr = require("socketMgr")
    local delay = 1
    local loopMessage
    loopMessage = function(premature)
    if premature then
    ngx_log(ngx_ERR, "timer was shut: ", err)
    return
    end
    socketMgr:loopMessages()
    local ok, err = ngx_timer_at(delay, loopMessage)
    if not ok then
    ngx_log(ngx_ERR, "failed to create the timer: ", err)
    return
    end
    end
    loopMessage()
    loopMessages

    判斷 local message id和 shared message id是否不等。

    隨后每次 local message id+ 1 從 shared拉取數據,進行消息推送邏輯。

    建立連接

    不做過多說明,自行查看 lua-resty-websocket的 wiki

    當連接監聽好之后,要進行一系列的管理。如:

    session id和 user id的雙向映射 session id和 group name的雙向映射

    后面再詳細說明

    生成 session id

    我是用 ( worker id+ 1) * 100000 + worker's local incr id來生成唯一 session id比較簡陋,但是夠用。

    這么做的原因是,通過對 session id進行取余可以很方便的得知 worker id,可以方便的給 shared寫消息。

    local ngx_worker_id = ngx.worker.id()local _incr_id = 0local _gen_session_id = function()_incr_id = _incr_id + 1return (ngx_worker_id + 1) * 100000 + _incr_idend 設置消息映射

    這個可以用于收到當前 worker所屬的 shared message判斷是否在當前進程。

    _messages[session_id] = {}_semaphores[session_id] = semaphore.new(0) 接收消息&;發送消息

    代碼和 官方例子類同不做過多說明,只說我改了什么。

    在接收消息中管理了一個變量即 close_flag用于管理 send message輕線程的退出。

    以下是一段偽代碼,含義的話請聯系上下文。

    local session_id = sessionMgr:gen_session_id()
    local send_semaphore = sessionMgr:get_semaphore(session_id)
    local close_flag = false
    local function _push_thread_function()
    while close_flag == false do
    local ok, err = send_semaphore:wait(300)
    if ok then
    local messages = socketMgr:getMessages(session_id)
    while messages and #messages > 0 do
    local message = messages[1]
    table_remove(messages, 1)
    --- your send message function handler
    end
    end
    if close_flag then
    socketMgr:destory(session_id)
    break
    end
    end
    end
    local push_thread = ngx_thread_spawn(_push_thread_function)
    while true do
    local data, typ, err = wbsocket:recv_frame()
    while err == "again" do
    local cut_data cut_data, _, err = wbsocket:recv_frame()
    data = data .. cut_data
    end
    if not data then
    close_flag = true
    send_semaphore:post(1)
    break
    elseif typ == 'close' then
    close_flag = true
    send_semaphore:post(1)
    break
    elseif typ == 'ping' then
    local bytes, err = wbsocket:send_pong(data)
    if not bytes then
    close_flag = true
    send_semaphore:post(1)
    break
    end
    elseif typ == 'pong' then
    elseif typ == 'text' then
    -- your receive function handler
    elseif typ == 'continuation' then
    elseif typ == 'binary' then
    end
    end
    ngx_thread_wait(push_thread)
    wbsocket:send_close() 消息推送

    現在說說為什么不用 shared的有序列表來存儲消息,我是使用了 shared的 set方法中的 flag屬性來存放 session id。

    這樣在獲得一個消息的時候,能很方便的知道消息是發給哪個 session id的。

    繼續一段偽代碼。

    local ngx_shared = ngx.shared
    local _shared_dicts = {ngx_shared.message_1,ngx_shared.message_2,ngx_shared.message_n,}
    local current_shared = _shared_dicts[ngx_worker_id + 1]
    local current_message_id = 1
    --- 如果在當前進程
    if _messages[session_id] then
    table.insert(_messages[session_id], "message data")
    _semaphores[session_id]:post(1)
    --- 會進入到,上述 _push_thread_function 方法中,進行發送邏輯
    else
    local shared_id = session_id % 100000
    local message_shared = _shared_dicts[shared_id]
    local message_id = message_shared:incr("id", 1, 0)
    message_shared:set("message." .. message_id, "message data", 60, session_id)
    end
    其他

    https://github.com/chenxiaofa/p

    借鑒了這位同學的設計思路,實現了額外邏輯。如:

    加入、退出、銷毀組 各 worker之間的 cmd內部命令執行 熱更新的特殊處理 等
posted on 2018-05-04 12:05 思月行云 閱讀(3231) 評論(0)  編輯 收藏 引用 所屬分類: Nginx\Openresty
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久久这里只有精品| 亚洲精品国产欧美| 亚洲欧美日韩精品在线| 正在播放欧美一区| av成人激情| 国产一区二区欧美| 欧美资源在线| 欧美va亚洲va国产综合| 亚洲狼人综合| 亚洲视频在线播放| 国产亚洲精品久久久久动| 另类人畜视频在线| 欧美寡妇偷汉性猛交| 亚洲一卡久久| 女主播福利一区| 国产在线精品一区二区中文| 欧美一区午夜视频在线观看| 亚洲午夜久久久久久久久电影院| 欧美成年人视频| 在线成人免费观看| 亚洲少妇中出一区| 亚洲高清免费在线| 你懂的视频一区二区| 亚洲最新色图| 久久免费少妇高潮久久精品99| 亚洲开发第一视频在线播放| 亚洲香蕉伊综合在人在线视看| 亚洲欧洲精品一区二区三区波多野1战4 | 久久女同互慰一区二区三区| 国产精品伦理| 亚洲调教视频在线观看| 亚洲欧洲综合另类| 美女图片一区二区| 亚洲一区二区3| 欧美国产日韩免费| 欧美成人第一页| 国产日韩欧美在线看| 日韩视频欧美视频| 亚洲日本电影| 欧美大片在线看免费观看| 亚洲欧美在线播放| 蜜桃av一区二区三区| 国产一区二区三区久久悠悠色av | 久久精品亚洲一区| 久久米奇亚洲| 欧美日韩午夜激情| 国产精品蜜臀在线观看| 国产一区二区三区在线播放免费观看| 国产日韩欧美电影在线观看| 国产一区二区三区精品欧美日韩一区二区三区 | 亚洲一区二区网站| 亚洲自拍偷拍色片视频| 夜夜夜精品看看| 一本色道久久综合狠狠躁篇的优点 | 久久国产精品免费一区| 久久久无码精品亚洲日韩按摩| 欧美一区二区在线视频| 久久成人免费日本黄色| 久久色中文字幕| 亚洲激情黄色| 欧美一级黄色网| 欧美黑人多人双交| 国产乱人伦精品一区二区| 黄色在线成人| 久久国产黑丝| 亚洲国产精品久久精品怡红院| 欧美一区二区精品在线| 欧美激情中文字幕乱码免费| 国产日韩精品久久久| 日韩一区二区精品在线观看| 午夜精品久久久久久久久久久久久| 裸体歌舞表演一区二区| 亚洲香蕉伊综合在人在线视看| 麻豆精品精品国产自在97香蕉| 精品动漫3d一区二区三区| 一区二区三区精品久久久| 久久躁日日躁aaaaxxxx| 欧美在线观看视频| 国产精品一区二区在线观看不卡 | 欧美一区二区三区播放老司机| 欧美激情一区在线| 99精品视频网| 久久综合色88| 欧美成人网在线| 亚洲美女毛片| 久久久一区二区三区| 亚洲系列中文字幕| 国产精品一国产精品k频道56| 亚洲一区二区三区在线视频| 亚洲日本欧美| 久久婷婷人人澡人人喊人人爽| 狠狠色综合一区二区| 久久免费视频这里只有精品| 久久精品国产清高在天天线| 欧美日韩中文字幕综合视频| 亚洲一区欧美一区| 亚洲一区区二区| 亚洲精品国精品久久99热| 亚洲免费激情| 国产精品久久久久9999高清 | 久久国产精品久久精品国产| 国色天香一区二区| 亚洲激情一区| 国产精品网站在线| 蜜桃视频一区| 国产精品久久久久久久久久久久久 | 欧美伊人久久久久久久久影院| 亚洲国产二区| 亚洲欧美制服另类日韩| 一本色道久久综合亚洲精品不卡| 亚洲永久免费视频| 国产一区二区视频在线观看| 亚洲国产精品国自产拍av秋霞| 欧美午夜精品伦理| 久久综合色婷婷| 国产精品久久一区主播| 亚洲电影在线免费观看| 国内综合精品午夜久久资源| 欧美电影免费观看高清完整版 | 日韩一级在线观看| 美女爽到呻吟久久久久| 欧美一区影院| 国产精品一香蕉国产线看观看 | 国产精品xxx在线观看www| 亚洲国产成人在线播放| 一区二区视频欧美| 久久久国产精品亚洲一区| 久久久久久久久综合| 国产日韩欧美中文在线播放| 日韩视频三区| 狠狠v欧美v日韩v亚洲ⅴ| 亚洲午夜久久久久久久久电影院| 狠狠干综合网| 先锋影音国产精品| 亚洲专区在线视频| 国产欧美日韩亚洲| 久久精品一区二区三区四区| 蜜臀久久99精品久久久久久9| 韩国三级电影久久久久久| 久久精品国产欧美激情| 蜜桃av一区二区三区| 最新69国产成人精品视频免费| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美国产一区视频在线观看| 中文一区二区| 久久久久成人精品| 亚洲国产日韩欧美在线99| 欧美日韩高清在线观看| 午夜精品一区二区三区四区| 久热精品在线| 亚洲欧美三级在线| 亚洲福利电影| 国产亚洲精品激情久久| 欧美国产日韩亚洲一区| 一本色道久久综合| 亚洲国产一区二区精品专区| 亚洲免费一区二区| 亚洲精品免费观看| 精品动漫一区| 国产在线成人| 国产一区二区久久| 国产女精品视频网站免费| 欧美乱在线观看| 欧美在线精品一区| 午夜伦理片一区| 国产精品久久久久久久久久久久久久| 亚洲福利一区| 欧美黑人在线观看| 欧美激情精品久久久久久| 欧美专区第一页| 久久最新视频| 免费欧美在线视频| 牛牛国产精品| 欧美激情按摩| 亚洲美女中文字幕| 一区二区三区视频观看| 久久久久久久精| 久久三级视频| 亚洲日本中文字幕| 亚洲网站在线播放| 中文久久精品| 欧美中文字幕精品| 久久字幕精品一区| 欧美精品一区二区三区久久久竹菊| 久久免费观看视频| 欧美视频一区二| 国产精品欧美日韩| 欧美日韩dvd在线观看| 国产亚洲精品久久久久婷婷瑜伽| 在线欧美日韩精品| 中文国产成人精品| 亚洲小说区图片区| 欧美电影免费观看高清完整版| 欧美福利小视频| 亚洲国产综合视频在线观看| 校园激情久久| 久久综合网络一区二区| 免费一区二区三区| 国产一区二区三区高清| 一区二区日韩免费看|