日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Cluster 集群

發布時間:2023/12/18 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cluster 集群 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

skynet 支持兩種集群模式。

如果你僅僅是單臺物理機的計算能力不足,那么最優的策略是選用更多核心的機器,在同一進程內,skynet 可以保持最高的并行能力,充分利用物理機的多核心,遠比增加物理機性價比高得多

master/slave 模式

當單臺機器的處理能力達到極限后,可以考慮通過內置的 master/slave 機制來擴展。具體的配置方法見?Config?。

每個 skynet 進程都是一個 slave 節點。但其中一個 slave 節點可以通過配置 standalone 來多啟動一個 cmaster 服務,用來協調 slave 組網。對于每個 slave 節點,都內置一個 harbor 服務用于和其它 slave 節點通訊。

每個 skynet 服務都有一個全網唯一的地址,這個地址是一個 32bit 數字,其高 8bit 標識著它所屬 slave 的號碼。即 harbor id 。在 master/slave 網絡中,id 為 0 是保留的。所以最多可以有 255 個 slave 節點。

在 master/slave 模式中,節點內的消息通訊和節點間的通訊是透明的。skynet 核心會根據目的地址的 harbor id 來決定是直接投遞消息,還是把消息轉發給 harbor 服務。但是,兩種方式的成本大為不同(可靠性也有所區別),在設計你的系統構架時,應充分考慮兩者的性能差異,不應視為相同的行為。

這種模式的缺點也非常明顯:它被設計為對單臺物理機計算能力不足情況下的補充。所以忽略了系統一部分故障的處理機制,而把整個網絡視為一體。即,整個網絡中任意一個節點都必須正常工作,節點間的聯系也不可斷開。這就好比你一臺物理機上如果插了多塊 CPU ,任意一個損壞都會導致整臺機器不能正常工作一樣。

所以,不要把這個模式用于跨機房的組網。所有 slave 節點都應該在同一局域網內(最好在同一交換機下)。不應該把系統設計成可以任意上線或下線 slave 的模式。

slave 的組網機制也限制了這一點。如果一個 slave 意外退出網絡,這個 harbor id 就被廢棄,不可再使用。這樣是為了防止網絡中其它服務還持有這個斷開的 slave 上的服務地址;而一個新的進程以相同的 harbor id 接入時,是無法保證舊地址和新地址不重復的。


如果你非要用 master/slave 模式來實現有一定彈性的集群。skynet 還是提供了非常有限的支持:

local harbor = require "skynet.harbor"
  • harbor.link(id)?用來監控一個 slave 是否斷開。如果 harbor id 對應的 slave 正常,這個 api 將阻塞。當 slave 斷開時,會立刻返回。

  • harbor.linkmaster()?用來在 slave 上監控和 master 的連接是否正常。這個 api 多用于異常時的安全退出(因為當 slave 和 master 斷開后,沒有手段可以恢復)。

  • harbor.connect(id)?和 harbor.link 相反。如果 harbor id 對應的 slave 沒有連接,這個 api 將阻塞,一直到它連上來才返回。

  • harbor.queryname(name)?可以用來查詢全局名字或本地名字對應的服務地址。它是一個阻塞調用。

  • harbor.globalname(name, handle)?注冊一個全局名字。如果 handle 為空,則注冊自己。skynet.name 和 skynet.register 是用其實現的。

你可以利用這組 api 來解決做一次跨節點遠程調用,因為節點斷開而無法收到回應的問題。注意:link 和 linkmaster 都有一定的開銷,所以最好在一個節點中只用少量服務調用它來監控組網狀態。由它再來分發到業務層。

對于 harbor id 不可復用的問題。你可以在?Config?中將 harbor 配置為引用一個系統環境變量。然后給 skynet 編寫一個啟動腳本,利用一個額外的程序去某個管理器中獲得尚未使用過的 harbor id ,設入環境變量,再啟動 skynet 進程。這些 skynet 沒有給出現成的解決方案,需要你自己來實現。

cluster 模式

skynet 提供了更具彈性的集群方案。它可以和 master/slave 共存。也就是說,你可以部署多組 master/slave 網絡,然后再用 cluster 將它們聯系起來。當然,比較簡單的結構是,每個集群中每個節點都配置為單節點模式(將 harbor id 設置為 0)。

要使用它之前,你需要編寫一個 cluster 配置文件,配置集群內所有節點的名字和對應的監聽端口。并將這個文件事先部署到所有節點,并寫在?Config?中。這個配置文件的范例見 examples/clustername.lua :

db = "127.0.0.1:2528"

這表示,集群中定義有一臺叫做 db 的節點,通訊端口為 127.0.0.1:2528 。

接下來,你需要在 db 的啟動腳本里寫上?cluster.open "db"?。示例見 examples/cluster1.lua 。

local skynet = require "skynet" local cluster = require "cluster"skynet.start(function()local sdb = skynet.newservice("simpledb")skynet.name(".simpledb", sdb)print(skynet.call(".simpledb", "lua", "SET", "a", "foobar"))print(skynet.call(".simpledb", "lua", "GET", "a"))cluster.open "db" end)

它啟動了 simpledb 這個服務,并起了一個本地名字 .simpledb ,然后打開了 db 節點的監聽端口。

在 examples/cluster2.lua 中示范了如何調用 db 上的 .simpledb 服務。( .simpledb 原本是一個本地服務,但通過 cluster 接口,其它節點也可以訪問到它。)

local skynet = require "skynet" local cluster = require "cluster"skynet.start(function()local proxy = cluster.proxy("db", ".simpledb")print(skynet.call(proxy, "lua", "GET", "a"))print(cluster.call("db", ".simpledb", "GET", "a")) end)

有兩種方式可以訪問到 db.simpledb :

  • 可以通過 cluster.call(nodename, service, ...) 提起請求。這里 nodename 就是在配置表中給出的節點名。service 可以是一個字符串,或者直接是一個數字地址(如果你能從其它渠道獲得地址的話)。當 service 是一個字符串時,只需要是那個節點可以見到的服務別名,可以是全局名或本地名。但更推薦是 . 開頭的本地名,因為使用 cluster 模式時,似乎沒有特別的理由還需要在那個節點上使用 master/slave 的架構(全局名也就沒有特別的意義)。

  • 可以通過 cluster.proxy(nodename, service) 生成一個本地代理。之后,就可以像訪問一個本地服務一樣,和這個遠程服務通訊。不過還是要遵循 cluster 的要求:遠程服務必須使用請求回應模式(不可以沒有返回值);必須使用 lua 協議。

  • 注意:你可以為同一個 skynet 進程(集群中的節點)配置多個通道。這種策略有時會更有效。因為一個通道僅由一條 TCP 連接保持通訊。如果你有高優先級的集群間調用需要處理,那么單獨開一個通道可能更好些。

    遠端名字服務

    你可以如上面一節所述的方式,給 skynet 的服務命名,然后使用字符串來替代數字地址。同時,cluster 還提供另一套命名方案。

    在本地進程內調用?cluster.register(name [,addr])?可以把 addr 注冊為 cluster 可見的一個字符串名字 name 。如果不傳 addr 表示把自身注冊為 name 。

    遠端可以通過調用?cluster.query(node, name)?查詢到這個名字對應的數字地址。如果名字不存在,則拋出 error 。

    由于歷史原因,這套命名方案和上一節的方案并存。但這節描述的方案更為推薦。因為這套命名體系僅在 cluster 的模塊中存在,并不影響 skynet 底層的命名系統,更容易為日后擴展。而 skynet 底層的命名系統已不再推薦使用。

    Cluster 配置更新

    Cluster 是去中心化的,所以需要在每臺機器上都放置一份配置文件(通常是相同的)。通過調用 cluster.reload 可以讓本進程重新加載配置。如果你修改了每個節點名字對應的地址,那么 reload 之后的請求都會發到新的地址。而之前沒有收到回應的請求還是會在老地址上等待。如果你老的地址已經無效(通常是主動關閉了進程)那么請求方會收到一個錯誤。

    在線上產品中如何向集群中的每個節點分發新的配置文件,skynet 并沒有提供方案。但這個方案一般比較容易實現。例如,你可以自己設計一個中心節點用來管理它。或者讓系統管理員編寫好同步腳本,并給程序加上控制指令來重載這些配置。

    Cluster 和?Snax?服務

    如果你使用?Snax?框架編寫服務,且服務需要通過 Cluster 調用。那么需要做一些額外的工作。

    首先,在?Snax?服務的 init 函數里,請調用一次?snax.enablecluster()?,否則它無法響應 Cluster 調用,而只能接收本地調用。

    其次,你需要保證調用方和提供服務的機器上都能打開 snax 腳本。

    如果全部條件滿足,那么你可以用?cluster.snax(node, name [,address])?來生成一個遠程 snax 服務對象。

    當你只給出 node 和 name 時,相當于去目標 node 上使用 snax.queryservice 獲取一個服務名對應的地址;如果給出了第三個參數 address ,那么 address 就是 snax 服務的地址,而 name 則是它的服務類型( 綁定 snax 服務需要這個類型,具體見 snax.bind )。



    總結

    以上是生活随笔為你收集整理的Cluster 集群的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。