PHPメッセージキュー
php-メッセージキューを実装し、共有メモリを介して通信を処理する 2 つのクラス
メッセージ キューを実装するには、Apache ActiveMQ、memcacheq... などのより専門的なツールを使用できます。ここでは 2 つの基本的で簡単な実装方法を示します。
memcache メソッドを使用して実現します
<?php /* * @Copyright (c) 2007,上海友邻信息科技有限公司 * @All rights reserved. * * 这个消息队列不是线程安全的,我只是尽量的避免了冲突的可能性。如果你要实现线程安全的,一个建议是通过文件进行锁定,然后进行操作。 * * @filename MemcacheQueue.class.php */ /** * Class and Function List: * Function list: * - __construct() * - singleton() * - init() * - __get() * - __set() * - isEmpty() * - isFull() * - enQueue() * - deQueue() * - getTop() * - getAll() * - getPage() * - makeEmpty() * - getAllKeys() * - add() * - increment() * - decrement() * - set() * - get() * - delete() * - getKeyByPos() * Classes list: * - Yl_MemcacheQueue */ class Yl_MemcacheQueue { private static $instance; private $memcache; private $name; private $prefix; private $maxSize; private function __construct() { } static function singleton() { if (! (self::$instance instanceof self)) { self::$instance = new Yl_MemcacheQueue (); } return self::$instance; } public function init($max_size, $name, $prefix = "__queue__") { $max_size = 1000; $name = '_war_'; $prefix = '_queue'; $this->memcache = Yl_Memcache::singleton (); $this->name = $name; $this->prefix = $prefix; $this->maxSize = $max_size; $this->add ( 'front', 0 ); $this->add ( 'rear', 0 ); $this->add ( 'size', 0 ); } function isEmpty() { return $this->get ( 'size' ) == 0; } function isFull() { return $this->get ( 'size' ) >= $this->maxSize; } function enQueue($data) { if ($this->isFull ()) { throw new Exception ( "Queue is Full" ); } $size = $this->increment ( 'size' ); $rear = $this->increment ( 'rear' ); $this->set ( ($rear - 1) % $this->maxSize, $data ); return $this; } function deQueue() { if ($this->isEmpty ()) { throw new Exception ( "Queue is Empty" ); } $this->decrement ( 'size' ); $front = $this->increment ( 'front' ); $this->delete ( ($front - 1) % $this->maxSize ); return $this; } function getTop() { return $this->get ( $this->get ( 'front' ) % $this->maxSize ); } function getAll() { return $this->getPage (); } function getPage($offset = 0, $limit = 0) { $size = $this->get ( 'size' ); if (0 == $size || $size < $offset) { return null; } $front = $this->get ( 'front' ) % $this->maxSize; $rear = $this->get ( 'rear' ) % $this->maxSize; $keys [] = $this->getKeyByPos ( ($front + $offset) % $this->maxSize ); $num = 1; for($pos = ($front + $offset + 1) % $this->maxSize; $pos != $rear; $pos = ($pos + 1) % $this->maxSize) { $keys [] = $this->getKeyByPos ( $pos ); $num ++; if ($limit > 0 && $limit == $num) { break; } } return array_values ( $this->memcache->get ( $keys ) ); } function makeEmpty() { $keys = $this->getAllKeys (); foreach ( $keys as $value ) { $this->delete ( $value ); } $this->delete ( "rear" ); $this->delete ( "front" ); $this->delete ( 'size' ); $this->delete ( "maxSize" ); } private function getAllKeys() { if ($this->isEmpty ()) { return array (); } $keys [] = $this->get ( 'front' ); for($pos = ($this->get ( 'front' ) % $this->maxSize + 1) % $this->maxSize; $pos != $this->get ( 'rear' ) % $this->maxSize; $pos = ($pos + 1) % $this->maxSize) { $keys [] = $pos; } return $keys; } private function add($pos, $data) { $this->memcache->add ( $this->getKeyByPos ( $pos ), $data ); return $this; } private function increment($pos) { return $this->memcache->increment ( $this->getKeyByPos ( $pos ) ); } private function decrement($pos) { $this->memcache->decrement ( $this->getKeyByPos ( $pos ) ); } private function set($pos, $data) { $this->memcache->save ( $data, $this->getKeyByPos ( $pos ) ); return $this; } private function get($pos) { return $this->memcache->get ( $this->getKeyByPos ( $pos ) ); } private function delete($pos) { return $this->memcache->delete ( $this->getKeyByPos ( $pos ) ); } private function getKeyByPos($pos) { return $this->prefix . $this->name . $pos; } } ?>
?
PHP を使用して Linux メッセージ キューを操作し、プロセス間通信を完了します
私たちが開発するシステムをマルチプロセス モードで実行する必要がある場合、プロセス間通信が重要なリンクになります。メッセージキューは、Linux システムにおけるプロセス間通信の方法です。
Linux システムプロセス通信の概念と実装については、http://www.ibm.com/developerworks/cn/linux/l-ipc/
を参照してください。
Linux システムにおけるメッセージキューの概念と実装については、http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/
を参照してください。
PHP の sysvmsg モジュールは、Linux システムでサポートされる System V IPC の System V メッセージ キュー関数ファミリーをカプセル化したものです。プロセス間通信には sysvmsg モジュールが提供する関数を使用する必要があります。まずサンプルコードを見てみましょう_1:
<?php $message_queue_key = ftok(__FILE__, 'a'); $message_queue = msg_get_queue($message_queue_key, 0666); var_dump($message_queue); $message_queue_status = msg_stat_queue($message_queue); print_r($message_queue_status); //向消息队列中写 msg_send($message_queue, 1, "Hello,World!"); $message_queue_status = msg_stat_queue($message_queue); print_r($message_queue_status); //从消息队列中读 msg_receive($message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT); print_r($message."\r\n"); msg_remove_queue($message_queue); ?>
resource(4) of type (sysvmsg queue) Array ( [msg_perm.uid] => 1000 [msg_perm.gid] => 1000 [msg_perm.mode] => 438 [msg_stime] => 0 [msg_rtime] => 0 [msg_ctime] => 1279849495 [msg_qnum] => 0 [msg_qbytes] => 16384 [msg_lspid] => 0 [msg_lrpid] => 0 ) Array ( [msg_perm.uid] => 1000 [msg_perm.gid] => 1000 [msg_perm.mode] => 438 [msg_stime] => 1279849495 [msg_rtime] => 0 [msg_ctime] => 1279849495 [msg_qnum] => 1 [msg_qbytes] => 16384 [msg_lspid] => 2184 [msg_lrpid] => 0 ) Hello,World!
サンプルコードの主な関数は以下のとおりです:
ftok ( string $pathname , string $proj ) 手册上给出的解释是:Convert a pathname and a project identifier to a System V IPC key。这个函数返回的键值唯一对应linux系统中一个消息队列。在获得消息队列的引用之前都需要调用这个函数。 msg_get_queue ( int $key [, int $perms ] ) msg_get_queue()会根据传入的键值返回一个消息队列的引用。如果linux系统中没有消息队列与键值对应,msg_get_queue()将会创建一个新的消息队列。函数的第二个参数需要传入一个int值,作为新创建的消息队列的权限值,默认为0666。这个权限值与linux命令chmod中使用的数值是同一个意思,因为在linux系统中一切皆是文件。 msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize [, bool $blocking [, int &$errorcode ]]] ) 顾名思义,该函数用来向消息队列中写数据。 msg_stat_queue ( resource $queue ) 这个函数会返回消息队列的元数据。消息队列元数据中的信息很完整,包括了消息队列中待读取的消息数、最后读写队列的进程ID等。示例代码在第8行调用该函数返回的数组中队列中待读取的消息数msg_qnum值为0。 msg_receive ( resource $queue , int $desiredmsgtype , int &$msgtype , int $maxsize , mixed &$message [, bool $unserialize [, int $flags [, int &$errorcode ]]] ) msg_receive用于读取消息队列中的数据。 msg_remove_queue ( resource $queue ) msg_remove_queue用于销毁一个队列。
<?php $message_queue_key = ftok ( __FILE__, 'a' ); $message_queue = msg_get_queue ( $message_queue_key, 0666 ); $pids = array (); for($i = 0; $i < 5; $i ++) { //创建子进程 $pids [$i] = pcntl_fork (); if ($pids [$i]) { echo "No.$i child process was created, the pid is $pids[$i]\r\n"; } elseif ($pids [$i] == 0) { $pid = posix_getpid (); echo "process.$pid is writing now\r\n"; msg_send ( $message_queue, 1, "this is process.$pid's data\r\n" ); posix_kill ( $pid, SIGTERM ); } } do { msg_receive ( $message_queue, 0, $message_type, 1024, $message, true, MSG_IPC_NOWAIT ); echo $message; //需要判断队列是否为空,如果为空就退出 //break; } while ( true ) ?>
No.0 child process was created, the pid is 5249 No.1 child process was created, the pid is 5250 No.2 child process was created, the pid is 5251 No.3 child process was created, the pid is 5252 No.4 child process was created, the pid is 5253 process.5251 is writing now this is process.5251's data process.5253 is writing now process.5252 is writing now process.5250 is writing now this is process.5253's data this is process.5252's data this is process.5250's data process.5249 is writing now this is process.5249's data
レディス
http://www.neatstudio.com/show-976-1.shtml
?
PHP に付属する 3 つのメッセージ キュー関連関数
http://www.zhangguangda.com/?p=89?