Python Message Queue package

Source: Internet
Author: User
Tags sendmsg

Python Message Queue package

1. Official introduction to the snakemq
The GitHub project page of the snail kemq: https://github.com/dsiroky/snakemq
1. Pure python implementation, cross-platform

2. Automatic Reconnection

3. reliable transmission-configurable message mode and message timeout Mode

4. Two types of persistent/Temporary queues

5. support asynchronous -- poll ()

6. duplex rical-a single TCP connection can be used for duplex communication

7. Support for multiple databases-SQLite, MongoDB ......

8. brokerless-implementation principle similar to ZeroMQ

9. expansion module: RPC, bandwidth throttling

All of the above are official words, which need to be verified by yourself and encapsulated by yourself. It feels cute.

II. Key Issues

1. Automatic reconnection is supported. You do not need to write your own heartbeat logic. You only need to pay attention to sending and receiving.

2. Data Persistence is supported. If persistence starts, data is automatically sent after reconnection.

3. For data receiving, you only need to write a Receiving Method to add it to the callback list.

4. The data is sent here in bytes (Binary) type, so conversion is required. All the tests in the program are text strings, which are converted to bytes using str. encode ('utf-8') and then converted back upon receiving.

5. in terms of terminology, Connector: similar to socket TcpClient, Lisenter: similar to socket TcpServer. Each connector or listener is identified by an ident one by one. When sending and receiving data, you will know who the data is.

6. When using sqlite for persistence, You need to modify the source code, sqlite3.connect (filename, check_same_thread = False), to solve the problem of multi-thread access to sqlite. (Will it be deadlocked ?)

7. When persistence is started, if it is re-connected, it will be automatically sent to ensure reliability.

8. After receiving data for encapsulation purposes, I use callback to transmit the data.

Iii. Code

The custom log module is used in the code.

from common import nxloggerimport snakemqlogger as logger

Can be replaced with logging.

Callback class (callbacks. py ):

# -*- coding:utf-8 -*-'''synchronized callback'''class Callback(object):  def __init__(self):    self.callbacks = []   def add(self, func):    self.callbacks.append(func)   def remove(self, func):    self.callbacks.remove(func)   def __call__(self, *args, **kwargs):    for callback in self.callbacks:      callback(*args, **kwargs)

Connector class (snkemqconnector. py ):

# -*- coding:utf-8 -*-import threadingimport snakemqimport snakemq.linkimport snakemq.packeterimport snakemq.messagingimport snakemq.messagefrom snakemq.storage.sqlite import SqliteQueuesStoragefrom snakemq.message import FLAG_PERSISTENTfrom common.callbacks import Callback from common import nxloggerimport snakemqlogger as logger class SnakemqConnector(threading.Thread):     def __init__(self, snakemqident = None, remoteIp = "localhost", remotePort = 9090, persistent = False):         super(SnakemqConnector,self).__init__()         self.messaging = None         self.link = None         self.snakemqident = snakemqident         self.pktr = None         self.remoteIp = remoteIp         self.remotePort = remotePort         self.persistent = persistent         self.on_recv = Callback()         self._initConnector()      def run(self):         logger.info("connector start...")                  if self.link != None:              self.link.loop()          logger.info("connector end...")         def terminate(self):         logger.info("connetor terminating...")         if self.link != None:              self.link.stop()              self.link.cleanup()         logger.info("connetor terminated")      def on_recv_message(self, conn, ident, message):         try:              self.on_recv(ident, message.data.decode('utf-8'))#dispatch received data         except Exception as e:              logger.error("connector recv:{0}".format(e))              print(e)      '''send message to dest host named destIdent'''     def sendMsg(self, destIdent, byteseq):         msg = None         if self.persistent:              msg = snakemq.message.Message(byteseq, ttl=60, flags=FLAG_PERSISTENT)         else:              msg = snakemq.message.Message(byteseq, ttl=60)         if self.messaging == None:              logger.error("connector:messaging is not initialized, send message failed")              return         self.messaging.send_message(destIdent, msg)      '''         '''     def _initConnector(self):         try:              self.link = snakemq.link.Link()              self.link.add_connector((self.remoteIp, self.remotePort))               self.pktr = snakemq.packeter.Packeter(self.link)               if self.persistent:                  storage = SqliteQueuesStorage("SnakemqStorage.db")                  self.messaging = snakemq.messaging.Messaging(self.snakemqident, "", self.pktr, storage)              else:                  self.messaging = snakemq.messaging.Messaging(self.snakemqident, "", self.pktr)                           self.messaging.on_message_recv.add(self.on_recv_message)                      except Exception as e:              logger.error("connector:{0}".format(e))         finally:              logger.info("connector[{0}] loop ended...".format(self.snakemqident))

Listener class (snkemqlistener. py ):

# -*- coding:utf-8 -*-import threadingimport snakemqimport snakemq.linkimport snakemq.packeterimport snakemq.messagingimport snakemq.messagefrom common import nxloggerimport snakemqlogger as loggerfrom common.callbacks import Callbackclass SnakemqListener(threading.Thread):     def __init__(self, snakemqident = None, ip = "localhost", port = 9090, persistent = False):         super(SnakemqListener,self).__init__()         self.messaging = None         self.link = None         self.pktr = None         self.snakemqident = snakemqident         self.ip = ip;         self.port = port         self.connectors = {}         self.on_recv = Callback()         self.persistent = persistent         self._initlistener()      '''     thread run     '''     def run(self):         logger.info("listener start...")                  if self.link != None:              self.link.loop()          logger.info("listener end...")      '''     terminate snakemq listener thread     '''     def terminate(self):         logger.info("listener terminating...")         if self.link != None:              self.link.stop()              self.link.cleanup()         logger.info("listener terminated")      '''     receive message from host named ident     '''     def on_recv_message(self, conn, ident, message):         try:              self.on_recv(ident, message.data.decode('utf-8'))#dispatch received data              self.sendMsg('bob','hello,{0}'.format(ident).encode('utf-8'))         except Exception as e:              logger.error("listener recv:{0}".format(e))              print(e)      def on_drop_message(self, ident, message):         print("message dropped", ident, message)         logger.debug("listener:message dropped,ident:{0},message:{1}".format(ident, message))      '''client connect'''     def on_connect(self, ident):         logger.debug("listener:{0} connected".format(ident))         self.connectors[ident] = ident         self.sendMsg(ident, "hello".encode('utf-8'))      '''client disconnect'''     def on_disconnect(self, ident):         logger.debug("listener:{0} disconnected".format(ident))         if ident in self.connectors:              self.connectors.pop(ident)      '''     listen start loop     '''     def _initlistener(self):         try:              self.link = snakemq.link.Link()              self.link.add_listener((self.ip, self.port))               self.pktr = snakemq.packeter.Packeter(self.link)              self.pktr.on_connect.add(self.on_connect)              self.pktr.on_disconnect.add(self.on_disconnect)               if self.persistent:                  storage = SqliteQueuesStorage("SnakemqStorage.db")                  self.messaging = snakemq.messaging.Messaging(self.snakemqident, "", self.pktr, storage)              else:                  self.messaging = snakemq.messaging.Messaging(self.snakemqident, "", self.pktr)                           self.messaging.on_message_recv.add(self.on_recv_message)              self.messaging.on_message_drop.add(self.on_drop_message)          except Exception as e:              logger.error("listener:{0}".format(e))         finally:              logger.info("listener:loop ended...")     '''send message to dest host named destIdent'''     def sendMsg(self, destIdent, byteseq):         msg = None         if self.persistent:              msg = snakemq.message.Message(byteseq, ttl=60, flags=FLAG_PERSISTENT)         else:              msg = snakemq.message.Message(byteseq, ttl=60)         if self.messaging == None:              logger.error("listener:messaging is not initialized, send message failed")              return         self.messaging.send_message(destIdent, msg)

Test code connector (testsnkeconnector. py ):

Read a local 1 M file and send it to the listener. Then, the listener sends back a hello message.

From netComm. snakemq import snkemqconnectorimport timeimport sysimport osdef inclued (ident, data): print (data) if _ name _ = "_ main _": bob = snkemqconnector. snkemqconnector ('bob', "10.16.5.45", 4002, True) bob. on_recv.add (received) bob. start () try: with open ("testfile.txt", encoding = 'utf-8') as f: txt = f. read () for I in range (100): bob. sendMsg ("niess", txt. encode ('utf-8') time. sleep (0.1) failed t Exception as e: print (e) time. sleep (5) bob. terminate () test code listener (testsnkelistener. py): from netComm. snakemq import snkemqlistenerimport time def received (ident, data): filename = "log/recfile1_02.16.txt ". format (time. strftime ('% s', time. localtime () file = open (filename, 'w') file. writelines (data) file. close () if _ name _ = "_ main _": niess = snkemqlistener. snemqlistener ("niess", "10.16.5.45", 4002) niess. on_recv.add (received) niess. start () print ("niess start... ") time. sleep (60) niess. terminate () print ("niess end... ")

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.