網路編程之python zeromq學習系列之一

來源:互聯網
上載者:User

標籤:

    簡介:      zeromq中介軟體,他是一個輕量級的訊息中介軟體,傳說是世界上最快的訊息中介軟體,為什麼這麼說呢?    因為一般的訊息中介軟體都需要啟動Message Service器,但是zeromq這廝盡然沒有Message Service器,他壓根沒有訊息中介軟體的架子,但是這並不能掩蓋他的強大。    通過和activemq,rabbitmq對比,顯然功能上沒有前兩者這麼強大,他不支援訊息的持久化,但是有訊息copy功能,他也不支援崩潰恢複,而且由於他太快了,可能用戶端還沒啟動,服務端的訊息就已經發出去了,這個就容易丟訊息了,但是zeromq自由他的辦法,就先說這麼多了。先來看看怎麼在python中引入這個強大的利器。    我自己之所以,學習體會一下,主要原因,是想在練習過程中體會其中的應用原理及邏輯,最好是能感知到其中的設計思想,為以後,自己做東西積攢點經驗.    另外最近也比較關注自動化營運的一些東西.網上說saltstack本身就用的zeromq做訊息佇列.所以更引起了我的興趣.    安裝:    我的作業系統是ubuntu 14.04的 python zeromq 環境安裝參考這裡的官網    下面測試:    一,C/S模式:    server 端代碼:        #!/usr/bin/env python        # coding:utf8        #author: [email protected]        import zmq        #調用zmq相關類方法,邦定連接埠        context = zmq.Context()        socket = context.socket(zmq.REP)        socket.bind(‘tcp://*:10001‘)        while True:            #迴圈接受用戶端發來的訊息            msg = socket.recv()            print "Msg info:%s" %msg            #向用戶端伺服器發端需要執行的命令            cmd_info = raw_input("client cmd info:").strip()            socket.send(cmd_info)        socket.close()    client 端代碼:      import zmq        import time        import commands        context = zmq.Context()        socket = context.socket(zmq.REQ)        socket.connect(‘tcp://127.0.0.1:10001‘)        def execut_cmd(cmd):            s,v = commands.getstatusoutput(cmd)            return v        while True:            #擷取目前時間            now_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())            socket.send("now time info:[%s] request execution command:‘\n‘,%s"%(now_time,result))            recov_msg = socket.recv()            #調用execut_cmd函數,執行伺服器發過來的命令            result = execut_cmd(recov_msg)            print recov_msg,‘\n‘,result,            time.sleep(1)            #print "now time info:%s cmd status:[%s],result:[%s]" %(now_time,s,v)            continue        socket.close()      注意:此模式是經典的接聽模式,不能同時send多個資料,        這種模式說是主要用於遠程調用和任務分配,但我愚笨,還是理解不透.後面有時間,再回過來好好看看,        測試:        req端        # python zmq-server-cs-v01.py        rep端        # python  zmq-client-cs-v01.py          二,發布訂閱模式(pub/sub)        pub 發布端代碼如下:        #!/usr/bin/env python        # coding:utf8        #author: [email protected]        import itertools        import sys,time,zmq        def main():            if len(sys.argv) != 2:                print ‘Usage: publisher‘                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)            msg_counter = itertools.count()            try:                for topic in itertools.cycle(all_topics):                msg_body = str(msg_counter.next())                #print msg_body,                print ‘Topic:%s,msg:%s‘ %(topic,msg_body)                s.send_multipart([topic,msg_body])                #s.send_pyobj([topic,msg_body])                time.sleep(0.1)            except KeyboardInterrupt:                pass            print "Wating for message queues to flush"            time.sleep(0.5)            s.close()            print "Done"        if __name__ == "__main__":        main()        sub  端代碼:            #!/usr/bin/env python            # coding:utf8            #author: [email protected]            import zmq            import time,sys            def main():            if len(sys.argv) < 2:                print "Usage: subscriber [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:                topics,msg = s.recv_multipart()                print ‘Topic:%s,msg:%s‘ %(topics,msg)            except KeyboardInterrupt:                pass            print "Done...."            if __name__ == "__main__":            main()     注意:     這裡的發布與訂閱角色是絕對的,即發行者無法使用recv,訂閱者不能使用send,官網還提供了一種可能出現的問題:當訂閱者消費慢於發布,     此時就會出現資料的堆積,而且還是在發布端的堆積(有朋友指出是堆積在消費端,或許是新版本改進,需要讀者的嘗試和反饋,thx!),顯然,     這是不可以被接受的。至於解決方案,或許後面的"分而治之"就是吧     測試:     pub端: 發布端      #python zmq-server-pubsub-v02.py  tcp://127.0.0.1:10001     sub端:訂閱端     #python zmq-server-cs-v01.py  tcp://127.0.0.1:10001 sports.football          三,push/pull 分而治之模式.          任務發布端代碼          #!/usr/bin/env python        # coding:utf8        #author: [email protected]        import zmq        import random        import time        context = zmq.Context()        #socket to send messages on        sender = context.socket(zmq.PUSH)        sender.bind(‘tcp://*:5557‘)        print ‘Press Enter when the workers are ready:‘        _ = raw_input()        print "Sending tasks to workers...."        #The first messages is "0" and signals start to batch        sender.send(‘0‘)        #Initialize random mumber generator        random.seed()        #send 100 tasks        total_msec = 0        for task_nbr in range(100):            #Random workload from 1 to 100 msecs            #print task_nbr,            workload = random.randint(1,100)            total_msec += workload            sender.send(str(workload))            print "Total expected cost:%s msec:%s workload:%s" %(total_msec,task_nbr,workload)        work端代碼如下:        #!/usr/bin/env python        # coding:utf8        #author: [email protected]        import sys,time,zmq        import commands        context = zmq.Context()        #socket to receive messages on        receiver = context.socket(zmq.PULL)        receiver.connect(‘tcp://127.0.0.1:5557‘)        #Socket to send messages to        sender = context.socket(zmq.PUSH)        sender.connect("tcp://127.0.0.1:5558")        #Process tasks forever        while True:            s = receiver.recv()            #Simple progress indicator for the viewer            print s,            sys.stdout.write("%s ‘\t‘ "%s)            sys.stdout.flush()            #Do the work            time.sleep(int(s)*0.001)            #Send results to sink            sender.send(s)    pull端代碼如下:            #!/usr/bin/env python            # coding:utf8            #author: [email protected]            import sys            import time            import zmq            context = zmq.Context()            #Socket to receive messages on            receiver = context.socket(zmq.PULL)            receiver.bind("tcp://*:5558")            #Wait for start of batch            s = receiver.recv()            #Start our clock now            tstart = time.time()            #Process 100 confirmations            total_msec = 0            for task_nbr in range(100):            s = receiver.recv()            if task_nbr % 10 == 0:                print task_nbr,                print s,                sys.stdout.write(‘:‘)            else:                print s,                #print task_nbr,                sys.stdout.write(‘.‘)            #Calculate and report duration of batch            tend = time.time()            print "Total elapsed time:%d msec "%((tend-tstart)*1000)    注意點:    這種模式與pub/sub模式一樣都是單向的,區別有兩點:    1,該模式下在沒有消費者的情況下,發行者的資訊是不會消耗的(由發行者進程維護)    2,多個消費者消費的是同一列資訊,假設A得到了一條資訊,則B將不再得到    這種模式主要針對在消費者能力不夠的情況下,提供的多消費者並行消費解決方案(也算是之前的pub/sub模式的    那個"堵塞問題"的一個解決方案策略吧)    其實所謂的分就是pull端去搶push端發出來的任務.誰搶著算誰的.    測試:     #python zmq-server-pushpull-v03.py     #python zmq-work-pushpull-v03.py     #python zmq-client-pushpull-v03.py     

網路編程之python zeromq學習系列之一

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.