只對比較簡單的direct模式進行了封裝,隊列支援持久化、鏡像以及auto-delete。
(但是不支援交換器的auto-delete,不知道擴充中為什麼沒與支援)
先執行消費者,建立對交換器、隊列並與路由鍵綁定,並監聽訊息佇列;
再執行生產者,向已建立的交換器中發送訊息。
直接上代碼了:
/** * 消費者類 */class AsynMessageConsumer{ private $config = array(); private $durable = True; private $mirror = False; private $autodelete = False; private $conn = Null; private $channel = Null; private $queue = Null; public $is_ready = False; /** * 建立串連、交換器、隊列,並綁定 * @param array $config RabbitMQ伺服器資訊 * @param string $e_name 交換器名稱 * @param string $k_route 路由鍵 * @param string $q_name 隊列名稱 * @param bool $durable 隊列是否持久化 * @param bool $mirror 隊列是否鏡像 * @return void */ public function __construct($config, $e_name, $k_route, $q_name, $durable = True, $mirror = False, $autodelete = False){ if (!($config && $e_name && $q_name && $k_route)) return False; $this->config = $config; if (!self::connect()) return False; $this->channel = new AMQPChannel($this->conn); $this->durable = (bool)$durable; $this->mirror = (bool)$mirror; $this->autodelete = (bool)$autodelete; $this->establishExchange($e_name); $this->establishQueue($q_name, $e_name, $k_route); $this->is_ready = True; } /** * 迴圈阻塞方式接收訊息 * @param string $fun_name 自訂處理函數的函數名 * @param bool $autoack 是否自動發送ACK應答,否則需要在自訂處理函數中手動發送 * @return bool */ public function run($fun_name, $autoack = True){ $fun_name = strval($fun_name); if (!$fun_name || !$this->queue) return False; while(True){ if ($autoack) $this->queue->consume($fun_name, AMQP_AUTOACK); else $this->queue->consume($fun_name); } } // 以下為私人方法,無需手動調用 /** * 建立連結 * 無法連結時則會自動選擇下一個配置項(IP不通的情況下會有5秒等待) * @param int $i 配置項索引 * @return bool */ private function connect($i = 0){ if (array_key_exists($i, $this->config)){ try{ $this->conn = new AMQPConnection($this->config[$i]); $this->conn->connect(); $ret = True; }catch(AMQPConnectionException $e){ $ret = $this->connect(++$i); } } else { $ret = False; } return $ret; } /** * 建立交換器 * @param string $name 名稱 * @return int */ private function establishExchange($name){ $ex = new AMQPExchange($this->channel); $ex->setName($name); $ex->setType(AMQP_EX_TYPE_DIRECT); //direct類型 if ($this->durable) $ex->setFlags(AMQP_DURABLE); //持久化 return $ex->declare(); } /** * 建立隊列 * @param string $name 名稱 * @param string $e_name 交換器名稱 * @param string $k_route 路由鍵 * @return int */ private function establishQueue($name, $e_name, $k_route){ $this->queue = new AMQPQueue($this->channel); $this->queue->setName($name); if ($this->durable) $this->queue->setFlags(AMQP_DURABLE); //持久化 if ($this->mirror) $this->queue->setArgument('x-ha-policy', 'all'); //鏡像 if ($this->autodelete) $this->queue->setFlags(AMQP_AUTODELETE); //auto-delete $this->queue->declare(); $ret = $this->queue->bind($e_name, $k_route); return $ret; } public function __destruct(){ if ($this->conn){ $this->conn->disconnect(); } }}
/** * 生產者類 */class AsynMessagePublisher{ private $config = array(); private $conn = Null; private $channel = Null; private $exchange = Null; public $is_ready = False; /** * 建立串連,並指定交換器 * @param array $config RabbitMQ伺服器資訊 * @param string $e_name 交換器名稱 * @return void */ public function __construct($config, $e_name){ if (!($config && $e_name)) return False; $this->config = $config; if (!self::connect()) return False; $this->channel = new AMQPChannel($this->conn); $this->establishExchange($e_name); $this->is_ready = True; } /** * 發送訊息 * @param string $msg 訊息體 * @param string $k_route 路由鍵 * @return int / False */ public function send($msg, $k_route){ $msg = trim(strval($msg)); if (!$this->exchange || $msg==='' || !$k_route) return False; $ret = $this->exchange->publish($msg, $k_route); return $ret; } // 以下為私人方法,無需手動調用 /** * 建立連結 * 無法連結時則會自動選擇下一個配置項(IP不通的情況下會有5秒等待) * @param int $i 配置項索引 * @return bool */ private function connect($i = 0){ if (array_key_exists($i, $this->config)){ try{ $this->conn = new AMQPConnection($this->config[$i]); $this->conn->connect(); $ret = True; }catch(AMQPConnectionException $e){ $ret = $this->connect(++$i); } } else { $ret = False; } return $ret; } /** * 建立交換器 * @param string $name 名稱 * @return void */ private function establishExchange($name){ $this->exchange = new AMQPExchange($this->channel); $this->exchange->setName($name); } public function __destruct(){ if ($this->conn){ $this->conn->disconnect(); } }}
使用比較簡單,demo例子就不給了。
實際應用中也可以再用原廠模式進行改造。