golang nats[5] cluster集群

集群模式

nats的集群模式對(duì)客戶端來說并不是透明的。
所以集群對(duì)發(fā)布者和訂閱者都是有影響的。
發(fā)布者和訂閱者都知道連接的是一個(gè)集群的服務(wù),而不是一個(gè)單點(diǎn)服務(wù),換句話說發(fā)布者訂閱者都必須指明集群中各個(gè)節(jié)點(diǎn)的地址僻他。
當(dāng)然笆包,發(fā)布者和訂閱者可以只針對(duì)集群中的某節(jié)點(diǎn)發(fā)布消息和訂閱消息环揽,不過這并不是集群模式的目的。

目的

提高可用性和可伸縮性庵佣。

實(shí)現(xiàn)原理

可用性歉胶,多個(gè)節(jié)點(diǎn),掛掉任意一個(gè)巴粪,不影響整個(gè)集群對(duì)外提供服務(wù)通今。
伸縮性,服務(wù)端支持隨意增加節(jié)點(diǎn)肛根。訂閱者可以感知服務(wù)端節(jié)點(diǎn)的變動(dòng)辫塌,但是發(fā)布者并不能自動(dòng)感知。

3個(gè)node的集群

$ gnatsd -p 4222 -m 4333 -cluster nats://localhost:4248 -routes nats://localhost:5248,nats://localhost:6248 -DV  
$ gnatsd -p 5222 -m 5333 -cluster nats://localhost:5248 -routes nats://localhost:4248,nats://localhost:6248 -DV 
$ gnatsd -p 6222 -m 6333 -cluster nats://localhost:6248 -routes nats://localhost:4248,nats://localhost:5248 -DV 

-p 端口:服務(wù)端口派哲,發(fā)布者臼氨,訂閱者需要使用此端口。
-m 端口: 監(jiān)控端口芭届。
-cluster 地址:作為集群節(jié)點(diǎn)對(duì)其他節(jié)點(diǎn)提供服務(wù)的地址储矩,其他節(jié)點(diǎn)需要連接的地址。(其他節(jié)點(diǎn)的-routes 可以填寫此地址)
-routes 地址:此節(jié)點(diǎn)喉脖,路由到其他地址的列表(也就是其他節(jié)點(diǎn)的-cluster)
-DV Debug and trace

gnatsd -p 服務(wù)提供端口 -m 服務(wù)監(jiān)控端口 -cluster 集群內(nèi)node地址 -routes 集群內(nèi)其他node地址列表 -DV

Server

package main

import (
    "github.com/nats-io/go-nats"
    "log"
    "flag"
    "fmt"
    "time"
)

const (
    //url   = "nats://192.168.3.125:4222"
    //url = nats.DefaultURL
    url = "nats://localhost:4222,nats://localhost:6222"
    //url = "nats://localhost:4222,nats://localhost:5222,nats://localhost:6222"
)

var (
    nc  *nats.Conn
    err error
)

func init() {

    if nc, err = nats.Connect(url, nats.DontRandomize(), nats.MaxReconnects(5), nats.ReconnectWait(2*time.Second), nats.DisconnectHandler(func(nc *nats.Conn) {
        fmt.Printf("Got disconnected!\n")
    }),
        nats.ReconnectHandler(func(_ *nats.Conn) {
            fmt.Printf("Got reconnected to %v!\n", nc.ConnectedUrl())
        }),
        nats.ClosedHandler(func(nc *nats.Conn) {
            fmt.Printf("Connection closed. Reason: %q\n", nc.LastError())
        }), nats.DiscoveredServersHandler(func(conn *nats.Conn) {
            fmt.Printf("Got Discover Server %v!\n", nc.ConnectedUrl())
        }), nats.ErrorHandler(func(conn *nats.Conn, subscription *nats.Subscription, e error) {
            fmt.Printf("Got Error Server %v!\n",e)
        })); checkErr(err) {
        //

    }
}

func main() {
    var (
        servername = flag.String("servername", "y", "name for server")
        queueGroup = flag.String("group", "", "group name for Subscribe")
        subj       = flag.String("subj", "abc", "subject name")
    )
    flag.Parse()

    log.Println(*servername, *queueGroup, *subj)
    startService(*subj, *servername+" worker1", *queueGroup)
    //startService(*subj, *servername+" worker2", *queueGroup)
    //startService(*subj, *servername+" worker3", *queueGroup)

    select {}
}

//receive message
func startService(subj, name, queue string) {
    go async(nc, subj, name, queue)
}

func async(nc *nats.Conn, subj, name, queue string) {
    _, e := nc.QueueSubscribe(subj, queue, func(msg *nats.Msg) {
        log.Println(name, "Received a message From Async : ", string(msg.Data))
    })

    checkErr(e)
}

func checkErr(err error) bool {
    if err != nil {
        log.Println("error:", err)
        return false
    }
    return true
}

Client

package main

import (
    "github.com/nats-io/go-nats"
    "log"
    "strconv"
    "github.com/pborman/uuid"
    "flag"
    "time"
    "fmt"
)

const (
    //url   = "nats://192.168.3.125:4222"
    //url = "nats://localhost:4222"
    //url = "nats://localhost:4222,nats://localhost:6222"
    url = "nats://localhost:4222,nats://localhost:5222,nats://localhost:6222"
    //url = "nats://localhost:5222"
)

var (
    nc  *nats.Conn
    err error
)

func init() {
    if nc, err = nats.Connect(url, nats.DontRandomize(), nats.MaxReconnects(10), nats.ReconnectWait(2*time.Second), nats.DisconnectHandler(func(nc *nats.Conn) {
        fmt.Printf("Got disconnected!\n")
    }),
        nats.ReconnectHandler(func(_ *nats.Conn) {
            fmt.Printf("Got reconnected to %v!\n", nc.ConnectedUrl())
        }),
        nats.ClosedHandler(func(nc *nats.Conn) {
            fmt.Printf("Connection closed. Reason: %q\n", nc.LastError())
        })); checkErr(err) {
        //
    }
    nc.SetDiscoveredServersHandler(func(conn *nats.Conn) {
        
    })
}

func main() {
    var (
        subj = flag.String("subj", "abc", "subject name")
    )
    flag.Parse()
    log.Println(*subj)
    startClient(*subj)

    time.Sleep(time.Second)
}

//send message to server
func startClient(subj string) {
    for i := 0; i < 1; i++ {
        id := uuid.New()
        log.Println(id)
        nc.Publish(subj, []byte(id+" Golang "+strconv.Itoa(i)))
        //nc.Publish(subj, []byte(id+" Rain "+strconv.Itoa(i)))
        //nc.Publish(subj, []byte(id+" Fog "+strconv.Itoa(i)))
        //nc.Publish(subj, []byte(id+" Cloudy "+strconv.Itoa(i)))
    }
}

func checkErr(err error) bool {
    if err != nil {
        log.Println(err)
        return false
    }
    return true
}

注意

  • 發(fā)布者和訂閱者都需要指明3個(gè)節(jié)點(diǎn)的ur地址
    nats://localhost:4222,nats://localhost:5222,nats://localhost:6222
  • 如果3個(gè)node都不可用椰苟,發(fā)布者會(huì)發(fā)送消息失敗。
  • 如果3個(gè)node至少有一個(gè)可用树叽,訂閱者就會(huì)收到消息舆蝴。
  • 如果3個(gè)node全都不可用,訂閱者會(huì)自動(dòng)斷開連接。
  • 增加一個(gè)node nats://localhost:7222,訂閱者可以自動(dòng)連接洁仗。
  • 增加node后层皱,3個(gè)node全都不可用,訂閱者不會(huì)斷開連接赠潦,可以接受從新node發(fā)布的消息叫胖。
  • 3個(gè)node恢復(fù)后,訂閱者可以接受3個(gè)node的消息她奥。

后續(xù)

發(fā)布者和訂閱者

  • 原始集群中node都不可用
  • 主動(dòng)查詢可用node
  • 接受可用node通知
  • 向可用node發(fā)送消息瓮增,訂閱可用node的消息
  • 以上內(nèi)容需要配合服務(wù)發(fā)現(xiàn)中間件或者自己實(shí)現(xiàn)

配置文件啟動(dòng)

$ gnatsd -c nodea.cfg
$ gnatsd -c nodeb.cfg
$ gnatsd -c nodec.cfg

nodea.cfg

listen: localhost:4222 # host/port to listen for client connections

http: localhost:4333 # HTTP monitoring port

# Authorization for client connections
#authorization {
  #user:     yasenagat
  # ./util/mkpasswd -p T0pS3cr3t
  #password: $2a$11$W2zko751KUvVy59mUTWmpOdWjpEm5qhcCZRd05GjI/sSOT.xtiHyG
  #ytc
  #token:   $2a$11$ZuYXelbdaRQnOcADEx40yOtinCvEi9c3X64K2Kyx7wLJq7ECPUnA2
  #timeout:  1
#}

# Cluster definition

cluster {

  listen: localhost:4248 # host/port for inbound route connections

  # Authorization for route connections
  #authorization {
    #user: user2
    # ./util/mkpasswd -p T0pS3cr3tT00!
    #password: $2a$11$xH8dkGrty1cBNtZjhPeWJewu/YPbSU.rXJWmS6SFilOBXzmZoMk9m
    #yctc
    #token: $2a$11$d/RrRseSiPOd/fxurspFquSirrjseRFRFGHdRbte7D8wj2laCLcVS
    #timeout: 0.5
  #}

  # Routes are actively solicited and connected to from this server.
  # Other servers can connect to us if they supply the correct credentials
  # in their routes definitions from above.

  routes = [
    nats-route://127.0.0.1:5248
    nats-route://127.0.0.1:6248
  ]
}

# logging options
debug:   false
trace:   true
logtime: false
log_file: "nodea.log"

# pid file
pid_file: "nodea.pid"

# Some system overides

# max_connections
max_connections: 100

# max_subscriptions (per connection)
max_subscriptions: 1000

# maximum protocol control line
max_control_line: 512

# maximum payload
max_payload: 65536

# Duration the server can block on a socket write to a client.  Exceeding the
# deadline will designate a client as a slow consumer.
write_deadline: "2s"

nodeb.cfg

listen: localhost:5222 # host/port to listen for client connections

http: localhost:5333 # HTTP monitoring port

# Authorization for client connections
authorization {
  #user:     yasenagat
  # ./util/mkpasswd -p T0pS3cr3t
  #password: $2a$11$W2zko751KUvVy59mUTWmpOdWjpEm5qhcCZRd05GjI/sSOT.xtiHyG
  #ytb
  token:   $2a$11$ToARKoxzTSTXxKCljOFe4eDmiPQ/EcaB0M7V8mGE1tfgOv97.iECe
  timeout:  1
}

# Cluster definition

cluster {

  listen: localhost:5248 # host/port for inbound route connections

  # Authorization for route connections
  authorization {
    #user: user1
    # ./util/mkpasswd -p T0pS3cr3tT00!
    #password: pass1
    #yctb
    token: $2a$11$EriHSUV8WO7PWUXTxOCY5uP7MhAswLE2tqQQPuz6kaoF89KhO8CcW
    timeout: 0.5
  }

  # Routes are actively solicited and connected to from this server.
  # Other servers can connect to us if they supply the correct credentials
  # in their routes definitions from above.

  routes = [
    nats-route://127.0.0.1:4248
    nats-route://127.0.0.1:6248
  ]
}

# logging options
debug:   false
trace:   true
logtime: false
log_file: "nodeb.log"

# pid file
pid_file: "nodeb.pid"

# Some system overides

# max_connections
max_connections: 100

# max_subscriptions (per connection)
max_subscriptions: 1000

# maximum protocol control line
max_control_line: 512

# maximum payload
max_payload: 65536

# Duration the server can block on a socket write to a client.  Exceeding the
# deadline will designate a client as a slow consumer.
write_deadline: "2s"

nodec.cfg

listen: localhost:6222 # host/port to listen for client connections

http: localhost:6333 # HTTP monitoring port

# Authorization for client connections
#authorization {
  #user:     yasenagat
  # ./util/mkpasswd -p T0pS3cr3t
  #password: $2a$11$W2zko751KUvVy59mUTWmpOdWjpEm5qhcCZRd05GjI/sSOT.xtiHyG
  #ytc
  #token:   $2a$11$HZy0M3lcxxzJRsFhtAoiX.jCuqKLyztcYYZPWRtlR.APhs/4mFYGC
  #timeout:  1
#}

# Cluster definition

cluster {

  listen: localhost:6248 # host/port for inbound route connections

  # Authorization for route connections
  #authorization {
    #user: user2
    # ./util/mkpasswd -p T0pS3cr3tT00!
    #password: $2a$11$xH8dkGrty1cBNtZjhPeWJewu/YPbSU.rXJWmS6SFilOBXzmZoMk9m
    #yctc
    #token: $2a$11$srwaIbFHGwIt37t3GrPynOHSpZ2LHTtw1QXWuznXGOaknEwulP4o6
    #timeout: 0.5
  #}

  # Routes are actively solicited and connected to from this server.
  # Other servers can connect to us if they supply the correct credentials
  # in their routes definitions from above.

  routes = [
    nats-route://127.0.0.1:5248
    nats-route://127.0.0.1:4248
  ]
}

# logging options
debug:   false
trace:   true
logtime: false
log_file: "nodec.log"

# pid file
pid_file: "nodec.pid"

# Some system overides

# max_connections
max_connections: 100

# max_subscriptions (per connection)
max_subscriptions: 1000

# maximum protocol control line
max_control_line: 512

# maximum payload
max_payload: 65536

# Duration the server can block on a socket write to a client.  Exceeding the
# deadline will designate a client as a slow consumer.
write_deadline: "2s"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市哩俭,隨后出現(xiàn)的幾起案子绷跑,更是在濱河造成了極大的恐慌,老刑警劉巖凡资,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砸捏,死亡現(xiàn)場離奇詭異,居然都是意外死亡隙赁,警方通過查閱死者的電腦和手機(jī)垦藏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伞访,“玉大人掂骏,你說我怎么就攤上這事『裰溃” “怎么了芭挽?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蝗肪。 經(jīng)常有香客問我,道長蠕趁,這世上最難降的妖魔是什么薛闪? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮俺陋,結(jié)果婚禮上豁延,老公的妹妹穿的比我還像新娘。我一直安慰自己腊状,他們只是感情好诱咏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缴挖,像睡著了一般袋狞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天苟鸯,我揣著相機(jī)與錄音同蜻,去河邊找鬼。 笑死早处,一個(gè)胖子當(dāng)著我的面吹牛湾蔓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播砌梆,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼默责,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咸包?” 一聲冷哼從身側(cè)響起桃序,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诉儒,沒想到半個(gè)月后葡缰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忱反,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年泛释,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片温算。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怜校,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出注竿,到底是詐尸還是另有隱情茄茁,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布巩割,位于F島的核電站裙顽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宣谈。R本人自食惡果不足惜愈犹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闻丑。 院中可真熱鬧漩怎,春花似錦、人聲如沸嗦嗡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侥祭。三九已至叁执,卻和暖如春茄厘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背徒恋。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國打工蚕断, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人入挣。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓亿乳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親径筏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子葛假,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Redis Cluster Specification 1 設(shè)計(jì)目標(biāo)和理由 1.1 Redis Cluster g...
    近路閱讀 4,250評(píng)論 0 12
  • feisky云計(jì)算、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 3,855評(píng)論 0 5
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理滋恬,服務(wù)發(fā)現(xiàn)聊训,斷路器,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 我們總是希望自己能夠更高效地利用時(shí)間恢氯,用最短的時(shí)間取得最大的效果带斑,那么下面內(nèi)容一定不要錯(cuò)過哦! 1.畫出你的“人生...
    小美的鵝會(huì)下蛋閱讀 745評(píng)論 1 8
  • 晚上我讀英語勋拟,首先我是讀80到90這塊兒的數(shù)勋磕,讀完以后,我覺得這些數(shù)都太少了敢靡,所以我又重新讀了一遍挂滓,結(jié)果全...
    家琦雅涵閱讀 178評(píng)論 0 0