zeroMQ初體驗-2.發佈訂閱模式(pub/sub)

 
pub/sub模式:



發佈端(pub)
Python代碼
import sys  
import time 
            
import zmq  
            
def main(): 
    if len (sys.argv) != 2:
        print 'usage: publisher <bind-to>'
        sys.exit (1)
    
    bind_to = sys.argv[1]
    
    all_topics = ['sports.general','sports.football','sports.basketball',
                  'stocks.general','stocks.GOOG','stocks.AAPL',
                  'weather']
    
    ctx = zmq.Context()
    s = ctx.socket(zmq.PUB)
    s.bind(bind_to)

    print "Starting broadcast on topics:"
    print "   %s" % all_topics
    print "Hit Ctrl-C to stop broadcasting."
    print "Waiting so subscriber sockets can connect..."
    print
    time.sleep(1.0)
    
    msg_counter = itertools.count()
    try:
        for topic in itertools.cycle(all_topics):
            msg_body = str(msg_counter.next())
            print '   Topic: %s, msg:%s' % (topic, msg_body)
            #s.send_multipart([topic, msg_body])
            s.send_pyobj([topic, msg_body])
            # short wait so we don't hog the cpu
            time.sleep(0.1)
    except KeyboardInterrupt:
        pass

    print "Waiting for message queues to flush..."
    time.sleep(0.5)
    s.close()
    print "Done."

if __name__ == "__main__":
    main()


訂閱端(sub):
Python代碼
import sys
import time
import zmq

def main():
    if len (sys.argv) < 2:
        print 'usage: subscriber <connect_to> [topic topic ...]'
        sys.exit (1)

    connect_to = sys.argv[1]
    topics = sys.argv[2:]

    ctx = zmq.Context()
    s = ctx.socket(zmq.SUB)
    s.connect(connect_to)

    # manage subscriptions
    if not topics:
        print "Receiving messages on ALL topics..."
        s.setsockopt(zmq.SUBSCRIBE,'')
    else:
        print "Receiving messages on topics: %s ..." % topics
        for t in topics:
            s.setsockopt(zmq.SUBSCRIBE,t)
    print
    try:
        while True:
            #topic, msg = s.recv_multipart()
            topic, msg = s.recv_pyobj()
            print '   Topic: %s, msg:%s' % (topic, msg)
    except KeyboardInterrupt:
        pass
    print "Done."

if __name__ == "__main__":
    main()


注意:
這裏的發佈與訂閱角色是絕對的,即發佈者無法使用recv,訂閱者不能使用send,並且訂閱者需要設置訂閱條件"setsockopt"。
按照官網的說法,在這種模式下很可能發佈者剛啓動時發佈的數據出現丟失,原因是用zmq發送速度太快,在訂閱者尚未與發佈者建立聯繫時,已經開始了數據發佈(內部局域網沒這麼誇張的)。官網給了兩個解決方案;1,發佈者sleep一會再發送數據(這個被標註成愚蠢的);2,(還沒有看到那,在後續中發現的話會更新這裏)。
官網還提供了一種可能出現的問題:當訂閱者消費慢於發佈,此時就會出現數據的堆積,而且還是在發佈端的堆積,顯然,這是不可以被接受的。至於解決方案,或許後面的"分而治之"就是吧。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章