golang nats queue模式

來源:互聯網
上載者:User

隊列訂閱模式

此模式中,訂閱者要指定兩個屬性,主題和隊列(queue,其實就是隊列名稱)

注意:下面所有前提=必須訂閱同一個主題

發布訊息後,N個具有同樣的主題和queue的訂閱者,只有一個會收到訊息。(random演算法)

說明:queue=工作群組,工作群組中有N個worker,發布訊息後,同一個工作群組中,僅有一個worker會收到訊息。

相同主題,不同queue的訂閱者之間,不符合上面的描述。這種情況下,可以把同一個queue的訂閱者們,當成一個訂閱者來處理,這樣就和普通的發布訂閱模式一樣了。

主題subj1,queue=q1的訂閱者有sub1-q1,sub2-q1,sub3-q1
主題subj1,queue=q2的訂閱者有sub1-q2,sub2-q2,sub3-q2
一個主題,兩組訂閱者,每組訂閱者中各有3個訂閱者。
對sub1發布訊息,q1,q2兩個組都會收到訊息(發布訂閱模式),q1,q2每個組中,分別僅有一個訂閱者會收到訊息(queue模式)

server

package mainimport (    "github.com/nats-io/go-nats"    "log"    "flag")const (    //url   = "nats://192.168.3.125:4222"    url = nats.DefaultURL)var (    nc  *nats.Conn    err error)func init() {    if nc, err = nats.Connect(url); 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", "", "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 messagefunc startService(subj, name, queue string) {    go async(nc, subj, name, queue)}func async(nc *nats.Conn, subj, name, queue string) {    nc.QueueSubscribe(subj, queue, func(msg *nats.Msg) {        log.Println(name, "Received a message From Async : ", string(msg.Data))    })}func checkErr(err error) bool {    if err != nil {        log.Println(err)        return false    }    return true}

client

package mainimport (    "github.com/nats-io/go-nats"    "log"    "strconv"    "github.com/pborman/uuid"    "flag"    "time")const (    //url   = "nats://192.168.3.125:4222"    url = nats.DefaultURL)var (    nc  *nats.Conn    err error)func init() {    if nc, err = nats.Connect(url); checkErr(err) {        //    }}func main() {    var (        subj = flag.String("subj", "", "subject name")    )    flag.Parse()    log.Println(*subj)    startClient(*subj)    time.Sleep(time.Second)}//send message to serverfunc startClient(subj string) {    for i := 0; i < 1; i++ {        id := uuid.New()        log.Println(id)        nc.Publish(subj, []byte(id+" Sun "+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}

啟動server A queue=g1,訂閱主題=weather

./main -servername=A -group=g1 -subj=weather2018/08/18 11:32:16 A g1 weather

啟動server B queue=g1,訂閱主題=weather

./main -servername=B -group=g1 -subj=weather2018/08/18 11:32:21 B g1 weather

發送訊息

./main -subj=weather2018/08/18 11:32:24 weather2018/08/18 11:32:24 3005ae7c-85ab-42d3-ad09-d44688d129ad

結果 server A收到訊息

2018/08/18 11:32:24 A worker3 Received a message From Async :  3005ae7c-85ab-42d3-ad09-d44688d129ad Rain 02018/08/18 11:32:24 A worker2 Received a message From Async :  3005ae7c-85ab-42d3-ad09-d44688d129ad Sun 0

結果 server B收到訊息

2018/08/18 11:32:24 B worker3 Received a message From Async :  3005ae7c-85ab-42d3-ad09-d44688d129ad Fog 02018/08/18 11:32:24 B worker3 Received a message From Async :  3005ae7c-85ab-42d3-ad09-d44688d129ad Cloudy 0

主題相同,queue不同

啟動server c queue=test,訂閱主題=weather

> ./main -servername=C -group=test -subj=weather2018/08/18 11:37:43 C test weather

發訊息

./main -subj=weather2018/08/18 11:37:47 weather2018/08/18 11:37:47 b4e201dd-ea4a-4ec3-aa45-99489695f0c2

Server c 收到了全部訊息

2018/08/18 11:37:47 C worker1 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Fog 02018/08/18 11:37:47 C worker3 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Sun 02018/08/18 11:37:47 C worker3 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Rain 02018/08/18 11:37:47 C worker3 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Cloudy 0

Server A 收到3條訊息

2018/08/18 11:37:47 A worker1 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Rain 02018/08/18 11:37:47 A worker3 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Sun 02018/08/18 11:37:47 A worker3 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Cloudy 0

Server B 收到1條訊息

2018/08/18 11:37:47 B worker2 Received a message From Async :  b4e201dd-ea4a-4ec3-aa45-99489695f0c2 Fog 0

總結:queue模式,在分發訊息時,進行負載平衡,隨機發送給同一組中的任意一個訂閱者,可以隨時增加刪除訂閱者,配合響應的監控資料和統計資料,對下遊的業務進行自動調整。

提高系統的可用性,避免業務在單點處理導致系統瓶頸。

栗子:
比如使用者登入,對login主題發送訊息,積分系統訂閱了login主題,收到login的訊息後,對使用者的積分進行處理。為了保證積分處理的高可用,可以使用相同的queue=score,啟動多個積分處理服務。
監控積分業務的處理時間,如果某個積分處理服務,業務執行時間過長(比如由於某些/某類使用者的特殊情況,積分演算法不同等),造成了訊息積壓,不能及時處理。

在積分系統的下遊仍有處理能力的時候(比如依賴下遊的某個介面,此介面的處理能力依然是正常的),可以自動啟動多個積分處理服務,訂閱主題login,queue=score,分散計算壓力。
如果是下遊的處理能力受限,則可能要進行限流處理,不但不能啟動多個積分處理服務,還要限制積分業務的處理速度。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.