RABBITMQ and PHP (ii)--related services installation and how to use PHP as the Guardian mode to process messages
In the previous section, the concepts of RABBITMQ exchange/routingkey/queue are described in detail, as well as examples of how to use PHP to send and process messages in code. This section describes how to use PHP Multi-threading for real-time message processing in the project, as well as a brief introduction to some RABBITMQ installation related. Familiar can be installed this section skipped.
First, the installation of RABBITMQ:
You need to install Erlang first
#安装jdk环境sudo apt-get Install openjdk-7-jdk# installation related class libraries and toolkits sudo apt-get install Libncurses5-dev M4 FOP Freeglut3-dev libwxgtk2 .8-dev g++ Libssl-dev xsltproc build-essential tk8.5 unixodbc unixodbc-dev libxml2-utils# download Erlang install package and install wget http:/ /WWW.ERLANG.ORG/DOWNLOAD/OTP_SRC_R16B03-1.TAR.GZTAR-XZVF OTP_SRC_R16B03-1.TAR.GZCD Otp_src_R16B03-1./configure-- Prefix=/usr/local/erlangmakesudo make Install
Note: Here the Erlang is installed in the specified directory:?/usr/local/erlang, instead of using the default path. This is a good habit, and will be beneficial for versioning. But does this lead to the back? RABBITMQ Error: Cannot find Erl? Executing the file requires more processing.
Update Environment variables:
sudo vi/etc/profile
In the last line add
Export Path=/usr/local/erlang/bin: $PATH
After saving exits
Source/etc/profile
Then enter the Erl on the command line to see if the installation was successful
Installing RABBITMQ
wget HTTP://WWW.RABBITMQ.COM/RELEASES/RABBITMQ-SERVER/V3.2.3/RABBITMQ-SERVER-GENERIC-UNIX-3.2.3.TAR.GZTAR-XZVF RABBITMQ-SERVER-GENERIC-UNIX-3.2.3.TAR.GZMV rabbitmq_server-3.2.3//usr/local/cd/usr/local/rabbitmq_server-3.2.3 /sbin./rabbitmq-server
Here if an error message appears:?. /rabbitmq-server:?line?86:?erl:?command?not?found?? This is because Erlang specifies the installation path, which is not found in the system's path. Just export? Path= $PATH:/usr/local/erlang/bin?
If it is convenient for rc.local to start, can you export? Path= $PATH:/usr/local/erlang/bin? This line is written to the? Rabbitmq-server file:
After the execution, Ps?-aux, see/usr/local/erlang/lib/erlang/erts-5.10.1/bin/epmd?-daemon in the process?/usr/local/erlang/lib/erlang/ ERTS-5.10.1/BIN/BEAM.SMP, it's OK.
There is also a script in the Sbin directory: Rabbitmqctl? is also very common, as with the rabbitmq-server? You need to specify the path of Erlang to work correctly.
Common methods:
Rabbitmqctl?start_app? After startup, do the comparison insurance rabbitmqctl?list_exchanges? Displays all current switch rabbitmqctl?list_queue? View current Active queue status
Second, the installation of php?extension:
PHP operation RABBITMQ requires support for AMQP extensions. Download extension: Http://pecl.php.net/package/amqp?, the installation process is the same as the general extension,
/usr/local/php/bin/phpize./configure?--with-php-config=/usr/local/php/bin/php-configsudo make?&&?make? Install
In the compilation and installation process if the error message, you can refer to this article: Ubuntu 12.04 installation rabbitmq PHP extension problems and solutions.
Then edit php.ini? Insert:
[amqp]extension?=?amqp.so
Restart Apache or nginx, see phpinfo There is a paragraph about anqp, OK.
Third, how to use PHP for real-time back-end message processing
First, make sure that the PHP file handles the message correctly and in a blocking manner. The code can be found in the previous section rabbitmq with PHP (i).
We then use Python to implement a multi-threaded daemon that invokes PHP and uses PHP as a worker thread.
startup script: start_jobs.py
# _*_ Coding:utf-8 _*_ "Yoka at Implementation of multithreading task Daemon created on 2012-4-7@author:xwarrior@update: [email protected] ' # The data package required for the introduction of the project from MyJobs import myjobsfrom MyThread import mythreadimport loggingimport timedef main (): Logger = logging . GetLogger (' main () ') logger.info (' Server start! ') Worker_threads = 2 #定义需要启动的线程数量 timeline = 2 #线程检查时间间隔, seconds Thread_pool = {} for I in range (0, worker_threads): param = ' some param ' job = myjobs (param) thread = MyThread (Job, i) Thread.setdaemon = True Thread.Start () logger.info (' Start thread%s '% (Thread.getname ())) thread_pool[i] = thread #干完就结束模式 #for Eachkey in Thread_pool.keys (): # Thread_pool[eachkey].join () #保持线程数量模式 while 1:time.sleep (Timeli NE) # Check each thread for Eachkey in Thread_pool.keys (): If Thread_pool[eachkey].isalive (): print ' thread alive: ' + str (i) Else:print ' thread down: ' + str (i) Thread_pool[eachkey].run () logger.info (' main exist! ') returnif __name__ = = ' __main__ ': #init config format = '% (asctime) -15s% (name) s% (levelname) s file% (filename ) S:lineno% (Lineno) s-% (message) s ' Logging.basicconfig (format=format,level=logging.info) main () Pass
Thread script:? mythread.py
# _*_ Coding:utf-8 _*_ "Created on 2013-03-25@author: [email protected]" from threading import ThreadClass MyThread (Thr EAD): ' Create thread ' ' def __init__ (self,job,thread_id): ' Constructor ' Self.job = Job thread.__init__ (self, name = ' my_thread_%s '% (thread_id)) def run (self): Self.job.run () C12/>def Stop (self): self.job.exit ()
Task script:? myjobs.py
# _*_ coding:utf-8 _*_ ' Created on 2013-03-25@author: [email protected] ' ' Import Osimport urllib2class myjobs (object): Def __init__ (self, param): #do something Self.param = para M def __del__ (self): "Destruct" Self.exit () def exit (self): ' exit ' Self.quit = True def run (self): ' Start processing ' #使用shell模式 #cmd = '/usr/bin/curl ' Http://at.yoka.com/try/amqp_con sume.php?key= ' + str (self.param) + ' "' cmd = '/usr/local/php/bin/php-c/usr/local/php/lib/nginx.ini/home/jimmy/at /documentroot/try/amqp_consume.php ' + str (self.param) re = Os.system (cmd) #使用web模式 #req = Urllib2. Request (' http://at.yoka.com/try/amqp_consume.php?key= ' + str (self.param)) #response = Urllib2.urlopen (req) # Re = Response.read () #print re
In task scheduling (start_jobs.py), two modes of operation are designed:
One mode of operation is to start n threads altogether to work, which is suitable for accomplishing a large task as soon as possible;
The other is to maintain the number of processes, and then restart the process when a process is found to be complete. Obviously, the user daemon handles messages that fit this pattern.
In myjob.py, the system shell is called and the URL is invoked in two ways. It is recommended that you use the Shell to invoke PHP directly, so you can control php.ini flexibly, such as increase auto_prepend_file, growth max_execution_time, etc.
In the actual project, assuming there are 5 types of messages, you can start 20 threads and pass thread_id as a parameter to PHP. PHP treats thread_id%5 as a pending type, so you can get a scenario where 4 threads work for each type.
Considering PHP's execution time limit and memory leak, the consume.php script can be improved to allow the PHP script to exit after each processing of a specified number of messages and to restart the thread from the Python multithreaded framework to ensure stable and reliable operation. Also, change the answer to manual response to ensure that the message is handled correctly and effectively.
/$q->consume (' ProcessMessage '); Need to manually answer/*** consumption callback function */function ProcessMessage ($envelope, $queue) { global $counter; $msg = $envelope->getbody (); echo $msg. " \ n "; Process message $queue->ack ($envelope->getdeliverytag ());//Send ACK reply manually if ($counter + + > 5) return FALSE;// Quit after processing 5 messages}
With two threads, check the interval 2 seconds, Shell mode? Test Run Results:
By visible, after the start of the run, check that 2 threads are active, and the message is processed correctly, when the PHP program ends after processing to a certain amount, the parent process checks to see that a process is in the completed state and restarts it (the second green box). Fully match the expectations.
?
Http://nonfu.me/p/8838.html