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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Cluster 集群

發(fā)布時(shí)間:2023/12/18 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cluster 集群 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

skynet 支持兩種集群模式。

如果你僅僅是單臺(tái)物理機(jī)的計(jì)算能力不足,那么最優(yōu)的策略是選用更多核心的機(jī)器,在同一進(jìn)程內(nèi),skynet 可以保持最高的并行能力,充分利用物理機(jī)的多核心,遠(yuǎn)比增加物理機(jī)性?xún)r(jià)比高得多

master/slave 模式

當(dāng)單臺(tái)機(jī)器的處理能力達(dá)到極限后,可以考慮通過(guò)內(nèi)置的 master/slave 機(jī)制來(lái)擴(kuò)展。具體的配置方法見(jiàn)?Config?。

每個(gè) skynet 進(jìn)程都是一個(gè) slave 節(jié)點(diǎn)。但其中一個(gè) slave 節(jié)點(diǎn)可以通過(guò)配置 standalone 來(lái)多啟動(dòng)一個(gè) cmaster 服務(wù),用來(lái)協(xié)調(diào) slave 組網(wǎng)。對(duì)于每個(gè) slave 節(jié)點(diǎn),都內(nèi)置一個(gè) harbor 服務(wù)用于和其它 slave 節(jié)點(diǎn)通訊。

每個(gè) skynet 服務(wù)都有一個(gè)全網(wǎng)唯一的地址,這個(gè)地址是一個(gè) 32bit 數(shù)字,其高 8bit 標(biāo)識(shí)著它所屬 slave 的號(hào)碼。即 harbor id 。在 master/slave 網(wǎng)絡(luò)中,id 為 0 是保留的。所以最多可以有 255 個(gè) slave 節(jié)點(diǎn)。

在 master/slave 模式中,節(jié)點(diǎn)內(nèi)的消息通訊和節(jié)點(diǎn)間的通訊是透明的。skynet 核心會(huì)根據(jù)目的地址的 harbor id 來(lái)決定是直接投遞消息,還是把消息轉(zhuǎn)發(fā)給 harbor 服務(wù)。但是,兩種方式的成本大為不同(可靠性也有所區(qū)別),在設(shè)計(jì)你的系統(tǒng)構(gòu)架時(shí),應(yīng)充分考慮兩者的性能差異,不應(yīng)視為相同的行為。

這種模式的缺點(diǎn)也非常明顯:它被設(shè)計(jì)為對(duì)單臺(tái)物理機(jī)計(jì)算能力不足情況下的補(bǔ)充。所以忽略了系統(tǒng)一部分故障的處理機(jī)制,而把整個(gè)網(wǎng)絡(luò)視為一體。即,整個(gè)網(wǎng)絡(luò)中任意一個(gè)節(jié)點(diǎn)都必須正常工作,節(jié)點(diǎn)間的聯(lián)系也不可斷開(kāi)。這就好比你一臺(tái)物理機(jī)上如果插了多塊 CPU ,任意一個(gè)損壞都會(huì)導(dǎo)致整臺(tái)機(jī)器不能正常工作一樣。

所以,不要把這個(gè)模式用于跨機(jī)房的組網(wǎng)。所有 slave 節(jié)點(diǎn)都應(yīng)該在同一局域網(wǎng)內(nèi)(最好在同一交換機(jī)下)。不應(yīng)該把系統(tǒng)設(shè)計(jì)成可以任意上線或下線 slave 的模式。

slave 的組網(wǎng)機(jī)制也限制了這一點(diǎn)。如果一個(gè) slave 意外退出網(wǎng)絡(luò),這個(gè) harbor id 就被廢棄,不可再使用。這樣是為了防止網(wǎng)絡(luò)中其它服務(wù)還持有這個(gè)斷開(kāi)的 slave 上的服務(wù)地址;而一個(gè)新的進(jìn)程以相同的 harbor id 接入時(shí),是無(wú)法保證舊地址和新地址不重復(fù)的。


如果你非要用 master/slave 模式來(lái)實(shí)現(xiàn)有一定彈性的集群。skynet 還是提供了非常有限的支持:

local harbor = require "skynet.harbor"
  • harbor.link(id)?用來(lái)監(jiān)控一個(gè) slave 是否斷開(kāi)。如果 harbor id 對(duì)應(yīng)的 slave 正常,這個(gè) api 將阻塞。當(dāng) slave 斷開(kāi)時(shí),會(huì)立刻返回。

  • harbor.linkmaster()?用來(lái)在 slave 上監(jiān)控和 master 的連接是否正常。這個(gè) api 多用于異常時(shí)的安全退出(因?yàn)楫?dāng) slave 和 master 斷開(kāi)后,沒(méi)有手段可以恢復(fù))。

  • harbor.connect(id)?和 harbor.link 相反。如果 harbor id 對(duì)應(yīng)的 slave 沒(méi)有連接,這個(gè) api 將阻塞,一直到它連上來(lái)才返回。

  • harbor.queryname(name)?可以用來(lái)查詢(xún)?nèi)置只虮镜孛謱?duì)應(yīng)的服務(wù)地址。它是一個(gè)阻塞調(diào)用。

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

你可以利用這組 api 來(lái)解決做一次跨節(jié)點(diǎn)遠(yuǎn)程調(diào)用,因?yàn)楣?jié)點(diǎn)斷開(kāi)而無(wú)法收到回應(yīng)的問(wèn)題。注意:link 和 linkmaster 都有一定的開(kāi)銷(xiāo),所以最好在一個(gè)節(jié)點(diǎn)中只用少量服務(wù)調(diào)用它來(lái)監(jiān)控組網(wǎng)狀態(tài)。由它再來(lái)分發(fā)到業(yè)務(wù)層。

對(duì)于 harbor id 不可復(fù)用的問(wèn)題。你可以在?Config?中將 harbor 配置為引用一個(gè)系統(tǒng)環(huán)境變量。然后給 skynet 編寫(xiě)一個(gè)啟動(dòng)腳本,利用一個(gè)額外的程序去某個(gè)管理器中獲得尚未使用過(guò)的 harbor id ,設(shè)入環(huán)境變量,再啟動(dòng) skynet 進(jìn)程。這些 skynet 沒(méi)有給出現(xiàn)成的解決方案,需要你自己來(lái)實(shí)現(xiàn)。

cluster 模式

skynet 提供了更具彈性的集群方案。它可以和 master/slave 共存。也就是說(shuō),你可以部署多組 master/slave 網(wǎng)絡(luò),然后再用 cluster 將它們聯(lián)系起來(lái)。當(dāng)然,比較簡(jiǎn)單的結(jié)構(gòu)是,每個(gè)集群中每個(gè)節(jié)點(diǎn)都配置為單節(jié)點(diǎn)模式(將 harbor id 設(shè)置為 0)。

要使用它之前,你需要編寫(xiě)一個(gè) cluster 配置文件,配置集群內(nèi)所有節(jié)點(diǎn)的名字和對(duì)應(yīng)的監(jiān)聽(tīng)端口。并將這個(gè)文件事先部署到所有節(jié)點(diǎn),并寫(xiě)在?Config?中。這個(gè)配置文件的范例見(jiàn) examples/clustername.lua :

db = "127.0.0.1:2528"

這表示,集群中定義有一臺(tái)叫做 db 的節(jié)點(diǎn),通訊端口為 127.0.0.1:2528 。

接下來(lái),你需要在 db 的啟動(dòng)腳本里寫(xiě)上?cluster.open "db"?。示例見(jiàn) 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)

它啟動(dòng)了 simpledb 這個(gè)服務(wù),并起了一個(gè)本地名字 .simpledb ,然后打開(kāi)了 db 節(jié)點(diǎn)的監(jiān)聽(tīng)端口。

在 examples/cluster2.lua 中示范了如何調(diào)用 db 上的 .simpledb 服務(wù)。( .simpledb 原本是一個(gè)本地服務(wù),但通過(guò) cluster 接口,其它節(jié)點(diǎn)也可以訪問(wèn)到它。)

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)

有兩種方式可以訪問(wèn)到 db.simpledb :

  • 可以通過(guò) cluster.call(nodename, service, ...) 提起請(qǐng)求。這里 nodename 就是在配置表中給出的節(jié)點(diǎn)名。service 可以是一個(gè)字符串,或者直接是一個(gè)數(shù)字地址(如果你能從其它渠道獲得地址的話)。當(dāng) service 是一個(gè)字符串時(shí),只需要是那個(gè)節(jié)點(diǎn)可以見(jiàn)到的服務(wù)別名,可以是全局名或本地名。但更推薦是 . 開(kāi)頭的本地名,因?yàn)槭褂?cluster 模式時(shí),似乎沒(méi)有特別的理由還需要在那個(gè)節(jié)點(diǎn)上使用 master/slave 的架構(gòu)(全局名也就沒(méi)有特別的意義)。

  • 可以通過(guò) cluster.proxy(nodename, service) 生成一個(gè)本地代理。之后,就可以像訪問(wèn)一個(gè)本地服務(wù)一樣,和這個(gè)遠(yuǎn)程服務(wù)通訊。不過(guò)還是要遵循 cluster 的要求:遠(yuǎn)程服務(wù)必須使用請(qǐng)求回應(yīng)模式(不可以沒(méi)有返回值);必須使用 lua 協(xié)議。

  • 注意:你可以為同一個(gè) skynet 進(jìn)程(集群中的節(jié)點(diǎn))配置多個(gè)通道。這種策略有時(shí)會(huì)更有效。因?yàn)橐粋€(gè)通道僅由一條 TCP 連接保持通訊。如果你有高優(yōu)先級(jí)的集群間調(diào)用需要處理,那么單獨(dú)開(kāi)一個(gè)通道可能更好些。

    遠(yuǎn)端名字服務(wù)

    你可以如上面一節(jié)所述的方式,給 skynet 的服務(wù)命名,然后使用字符串來(lái)替代數(shù)字地址。同時(shí),cluster 還提供另一套命名方案。

    在本地進(jìn)程內(nèi)調(diào)用?cluster.register(name [,addr])?可以把 addr 注冊(cè)為 cluster 可見(jiàn)的一個(gè)字符串名字 name 。如果不傳 addr 表示把自身注冊(cè)為 name 。

    遠(yuǎn)端可以通過(guò)調(diào)用?cluster.query(node, name)?查詢(xún)到這個(gè)名字對(duì)應(yīng)的數(shù)字地址。如果名字不存在,則拋出 error 。

    由于歷史原因,這套命名方案和上一節(jié)的方案并存。但這節(jié)描述的方案更為推薦。因?yàn)檫@套命名體系僅在 cluster 的模塊中存在,并不影響 skynet 底層的命名系統(tǒng),更容易為日后擴(kuò)展。而 skynet 底層的命名系統(tǒng)已不再推薦使用。

    Cluster 配置更新

    Cluster 是去中心化的,所以需要在每臺(tái)機(jī)器上都放置一份配置文件(通常是相同的)。通過(guò)調(diào)用 cluster.reload 可以讓本進(jìn)程重新加載配置。如果你修改了每個(gè)節(jié)點(diǎn)名字對(duì)應(yīng)的地址,那么 reload 之后的請(qǐng)求都會(huì)發(fā)到新的地址。而之前沒(méi)有收到回應(yīng)的請(qǐng)求還是會(huì)在老地址上等待。如果你老的地址已經(jīng)無(wú)效(通常是主動(dòng)關(guān)閉了進(jìn)程)那么請(qǐng)求方會(huì)收到一個(gè)錯(cuò)誤。

    在線上產(chǎn)品中如何向集群中的每個(gè)節(jié)點(diǎn)分發(fā)新的配置文件,skynet 并沒(méi)有提供方案。但這個(gè)方案一般比較容易實(shí)現(xiàn)。例如,你可以自己設(shè)計(jì)一個(gè)中心節(jié)點(diǎn)用來(lái)管理它。或者讓系統(tǒng)管理員編寫(xiě)好同步腳本,并給程序加上控制指令來(lái)重載這些配置。

    Cluster 和?Snax?服務(wù)

    如果你使用?Snax?框架編寫(xiě)服務(wù),且服務(wù)需要通過(guò) Cluster 調(diào)用。那么需要做一些額外的工作。

    首先,在?Snax?服務(wù)的 init 函數(shù)里,請(qǐng)調(diào)用一次?snax.enablecluster()?,否則它無(wú)法響應(yīng) Cluster 調(diào)用,而只能接收本地調(diào)用。

    其次,你需要保證調(diào)用方和提供服務(wù)的機(jī)器上都能打開(kāi) snax 腳本。

    如果全部條件滿(mǎn)足,那么你可以用?cluster.snax(node, name [,address])?來(lái)生成一個(gè)遠(yuǎn)程 snax 服務(wù)對(duì)象。

    當(dāng)你只給出 node 和 name 時(shí),相當(dāng)于去目標(biāo) node 上使用 snax.queryservice 獲取一個(gè)服務(wù)名對(duì)應(yīng)的地址;如果給出了第三個(gè)參數(shù) address ,那么 address 就是 snax 服務(wù)的地址,而 name 則是它的服務(wù)類(lèi)型( 綁定 snax 服務(wù)需要這個(gè)類(lèi)型,具體見(jiàn) snax.bind )。



    總結(jié)

    以上是生活随笔為你收集整理的Cluster 集群的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。