Python Development Program: RPC asynchronous command execution (RabbitMQ bidirectional communication), pythonrabbitmq
RPC asynchronous Command Execution
Requirements:
- Use RibbitMQ for Data Interaction
- Allows you to operate on multiple servers.
- After the command is executed, you do not need to wait for the command execution result. Instead, you can directly input the next command and print the result automatically.
- Implement Asynchronous operations
Do not understand rpc please move to the http://www.cnblogs.com/lianzhilei/p/5977545.html (bottom)
This section involves the most about rabbitmq Communication Principles and requires the installation of the rabbitmq service.
Program directory structure:
Program introduction:
# Asynchronous rpc program # blog Address [11th days blog address] (http://www.cnblogs.com/lianzhilei/p/5970176.html) (http://www.cnblogs.com/lianzhilei/p/5970176.html) #1. requirement-[] Use RibbitMQ for Data Interaction-[] operations on multiple servers-[] do not wait for the command execution result after the command is executed, instead, you can directly input the next command and print the result automatically-[] implement asynchronous operations # Note-[] RabbitMQ queue name: ① when executing the command, the queue name is the IP address of the server. ② When querying data, the callback_queue name randomly generated during callback-[] threading multithreading is used: the command is executed without waiting for the execution result, you can still enter the new command-[] execution command format: --> run "dir" host 192.168.20.22 192.168.20.23 the command host to be executed by the dir server can be followed by one or more server addresses of rabbitMQ-[] to view all backend task_ids information: --> check_all: TASK_ID [76786] HOST [192.168.20.22] COMMAND [dir] TASK_ID [10307] HOST [192.168.20.23] COMMAND [dir]-[] view the execution result of TASK_ID: --> check_task 10307 10307 is the TASK_ID found by check_all.
README. md
Program flowchart:
Server:
#! /Usr/bin/env python #-*-coding: UTF-8-*-#-Author-Lian #! /Usr/bin/env python #-*-coding: UTF-8-*-#-Author-Lianimport pikaimport osclass Server (object): def _ init _ (self, rabbitmq, queue_name): self. queue_name = queue_name self. connection = pika. blockingConnection (pika. connectionParameters (host = rabbitmq) self. channel = self. connection. channel () self. channel. queue_declare (queue = self. queue_name) def handle (self, command): command = command. decode () print (command, type (command) message = OS. popen (command ). read () if not message: message = "Wrong Command" return message def on_request (self, ch, method, props, body): response = self. handle (body) ch. basic_publish (exchange = '', routing_key = props. reply_to, # return information queue name properties = pika. basicProperties (correlation_id = props. correlation_id), body = str (response) ch. basic_ack (delivery_tag = method. delivery_tag) def start (self): self. channel. basic_consume (self. on_request, queue = self. queue_name) print ("[x] Awaiting RPC requests") self. channel. start_consuming () if _ name _ = "_ main __": rabbitmq = "localhost" # rabbitmq server address queue_name = "192.168.20.22" # queue_name is the local IP address Server = server (rabbitmq, queue_name) server. start ()
Server. py
Client:
Bin directory:
#! /Usr/bin/env python #-*-coding: UTF-8-*-import sysimport osimport platform # Add BASE_DIR and add the top-level directory to the path to facilitate calling other directory modules if platform. system () = 'windows': print (OS. path. abspath (OS. path. dirname (_ file __)). split ('\') [:-1]) BASE_DIR = '\\'. join (OS. path. abspath (OS. path. dirname (_ file __)). split ('\') [:-1]) else: BASE_DIR = '/'. join (OS. path. abspath (OS. path. dirname (_ file __)). split ('/') [:-1]) # load the environment variable sys. path. append (BASE_DIR) from conf import settingsfrom core import mainif _ name _ = '_ main _': obj = main. handler () obj. start ()
Start. py
Conf directory:
#! /Usr/bin/env python #-*-coding: UTF-8-*-_ author _ = 'luotianshuai' import osimport sysimport platformif platform. system () = 'windows': BASE_DIR = '\\'. join (OS. path. abspath (OS. path. dirname (_ file __)). split ('\') [:-1]) school_dbpaths = OS. path. join (BASE_DIR, 'school _ db') else: BASE_DIR = '/'. join (OS. path. abspath (OS. path. dirname (_ file __)). split ('/') [:-1]) school_dbpaths = OS. path. join (BASE_DIR, 'school _ db') # rabbitmq service address ipRabbitMQ_IP = 'localhost'
Settings. py
Core directory
#! /Usr/bin/env python #-*-coding: UTF-8-*-#-Author-Lianfrom conf import settingsfrom modules. client import Clientimport random, timeimport threadingclass Handler (object): def _ init _ (self): self. information ={}# background process information def check_all (self, * args): ''' view all task_id information ''' time. sleep (2) for key in self. information: print ("TASK_ID [% s] \ tHOST [% s] \ tCOMMAND [% s]" % (key, self. information [key] [0], self. information [key] [1]) def check_task (self, user_cmd): ''' view task_id execution result ''' time. sleep (2) try: task_id = user_assist.split () [1] task_id = int (task_id) callback_queue = self. information [task_id] [2] callback_id = self. information [task_id] [3] client = Client () response = client. get_response (callback_queue, callback_id) print (response. decode () del self. information [task_id] doesn t KeyError as e: print ("\ 33 [31; 0 mWrong id [% s] \ 33 [0 m" % e) Doesn't IndexError as e: print ("\ 33 [31; 0 mWrong id [% s] \ 33 [0 m" % e) def run (self, user_cmd ): '''execute the command ''' try: time. sleep (2) # print ("--->", user_cmd) command = user_assist.split ("\" ") [1] hosts = user_assist.split () [3:] for host in hosts: task_id = random. randint (10000,999 99) client = Client () response = client. call (host, command) # print (response) self. information [task_id] = [host, command, response [0], response [1] handle T IndexError as e: print ("\ 33 [31; 0 mError: % s \ 33 [0 m "% e) def reflect (self, str, user_cmd): '''reflection ''' if hasattr (self, str): getattr (self, str) (user_cmd) # else: # setattr (self, str, self. foo) # getattr (self, str) () def start (self): while True: user_cmd = input ("-> "). strip () if not user_cmd: continue str = user_assist.split () [0] t1 = threading. thread (target = self. reflect, args = (str, user_cmd) # multithreading t1.start ()
Main. py
Modules directory
#! /Usr/bin/env python #-*-coding: UTF-8-*-#-Author-Lianimport pikaimport uuidfrom conf import settingsclass Client (object ): def _ init _ (self): self. connection = pika. blockingConnection (pika. connectionParameters (host = settings. rabbitMQ_IP) self. channel = self. connection. channel () def on_response (self, ch, method, props, body): ''' callback function for obtaining command execution results ''' # print ("Verification code check", self. callback_id, props. correlation_id) if self. callback_id = props. correlation_id: # verify self with the verification code. response = body ch. basic_ack (delivery_tag = method. delivery_tag) def get_response (self, callback_queue, callback_id): ''' get the value in the queue and obtain the callback_queued execution result ''' self. callback_id = callback_id self. response = None self. channel. basic_consume (self. on_response, # Run on_response queue = callback_queue) while self. response is None: self. connection. process_data_events () # start_consuming return self. response def call (self, queue_name, command): ''' data sent in the queue ''' result = self. channel. queue_declare (exclusive = False) # exclusive = False must be written in this way. callback_queue = result. method. queue self. required _id = str (uuid. uuid4 () # print (self. consumed _id) self. channel. basic_publish (exchange = '', routing_key = queue_name, properties = pika. basicProperties (reply_to = self. callback_queue, # name correlation_id = self. required _id, # Send the uuid equivalent to the Verification Code), body = command) return self. callback_queue, self. consumer _id
Client. py
Running example