php队列封装,基于System V Message queue的PHP消息队列封装

System V Message queue 是一种进程通信(IPC)的方式,方便实现生产者-消费者模型,单个或多个生产者向队列中写入消息,多个生产者再从队列中获取消息进行处理。

该Wrapper支持:进程通信

设置最大队列容量(字节单位)

获取当前队列数量

修改队列部分属性

注意:如果要修改队列最大容量,请确保你的脚本是运行在root下<?php

/**

* Created by PhpStorm.

* User: huyanping

* Date: 14-8-9

* Time: 上午3:44

*

* System V message queue IPC通信消息队列封装

* 如果你想修改一个队列最大能够存储的字节数,请确认你的脚本具有root权限

*/

class SystemVMessageQueue implements IMessageQueue

{

//消息分组类型,用于将一个消息队列中的信息进行分组

private $msg_type;

//队列标志

private $queue;

//是否序列化

private $serialize_needed;

//无法写入队列时,是否阻塞

private $block_send;

//设置位MSG_IPC_NOWAIT,如果无法获取到一个消息,则不等待;如果设置位NULL,则会等待消息到来

private $option_receive;

//希望接收到的最大消息大小

private $maxsize;

//IPC通信KEY

private $key_t;

/**

* @param $ipc_filename IPC通信标志文件,用于获取唯一IPC KEY

* @param $msg_type 消息类型

* @param bool $serialize_needed 是否序列化

* @param bool $block_send 无法写入队列时,是否阻塞

* @param int $option_receive 设置位MSG_IPC_NOWAIT,如果无法获取到一个消息,则不等待;如果设置位NULL,则会等待消息到来

* @param int $maxsize 希望接收到的最大消息

*/

public function __construct($msg_type, $ipc_filename = __FILE__, $serialize_needed = true, $block_send = false, $option_receive = MSG_IPC_NOWAIT, $maxsize = 100000)

{

$this->msg_type = $msg_type;

$this->serialize_needed = $serialize_needed;

$this->block_send = $block_send;

$this->option_receive = $option_receive;

$this->maxsize = $maxsize;

$this->init_queue($ipc_filename, $msg_type);

}

/**

* 初始化一个队列

* @param $ipc_filename

* @param $msg_type

* @throws Exception

*/

public function init_queue($ipc_filename, $msg_type)

{

$this->key_t = $this->get_ipc_key($ipc_filename, $msg_type);

$this->queue = msg_get_queue($this->key_t);

if (!$this->queue) throw new Exception('msg_get_queue failed');

}

/**

* @param $ipc_filename

* @param $msg_type

* @return int

* @throws Exception

*/

public function get_ipc_key($ipc_filename, $msg_type)

{

$key_t = ftok($ipc_filename, $msg_type);

if ($key_t == 0) throw new Exception('ftok error');

return $key_t;

}

/**

* 从队列获取一个

* @return bool

* @throws Exception

*/

public function get()

{

$queue_status = $this->status();

if ($queue_status['msg_qnum'] > 0) {

if (msg_receive($this->queue, $this->msg_type, $msgtype_erhalten, $this->maxsize, $data, $this->serialize_needed, $this->option_receive, $err) === true) {

return $data;

} else {

throw new Exception($err);

}

} else {

return false;

}

}

/**

* 写入队列

* @param $message

* @throws Exception

*/

public function put($message)

{

if (!msg_send($this->queue, $this->msg_type, $message, $this->serialize_needed, $this->block_send, $err) === true) {

throw new Exception($err);

}

return true;

}

/*

* 返回值数组下标如下:

* msg_perm.uid The uid of the owner of the queue. 用户ID

* msg_perm.gid The gid of the owner of the queue. 用户组ID

* msg_perm.mode The file access mode of the queue. 访问模式

* msg_stime The time that the last message was sent to the queue. 最后一次队列写入时间

* msg_rtime The time that the last message was received from the queue.  最后一次队列接收时间

* msg_ctime The time that the queue was last changed. 最后一次修改时间

* msg_qnum The number of messages waiting to be read from the queue. 当前等待被读取的队列数量

* msg_qbytes The maximum number of bytes allowed in one message queue.  一个消息队列中允许接收的最大消息总大小

*               On Linux, this value may be read and modified via /proc/sys/kernel/msgmnb.

* msg_lspid The pid of the process that sent the last message to the queue. 最后发送消息的进程ID

* msg_lrpid The pid of the process that received the last message from the queue. 最后接收消息的进程ID

*

* @return array

*/

public function status()

{

$queue_status = msg_stat_queue($this->queue);

return $queue_status;

}

/**

* 获取队列当前堆积状态

* @return mixed

*/

public function size()

{

$status = $this->status();

return $status['msg_qnum'];

}

/**

* allows you to change the values of the msg_perm.uid,

* msg_perm.gid, msg_perm.mode and msg_qbytes fields of the underlying message queue data structure

* 可以用来修改队列运行接收的最大读取的数据

*

* @param $key 状态下标

* @param $value 状态值

* @return bool

*/

public function set_status($key, $value)

{

$this->check_set_privilege($key);

if ($key == 'msg_qbytes')

return $this->set_max_queue_size($value);

$queue_status[$key] = $value;

return msg_set_queue($this->queue, $queue_status);

}

/**

* 删除一个队列

* @return bool

*/

public function queue_remove()

{

return msg_remove_queue($this->queue);

}

//修改队列能容纳的最大字节数,需要root权限

/**

* @param $size

* @return bool

* @throws Exception

*/

public function set_max_queue_size($size)

{

$user = get_current_user();

if ($user !== 'root')

throw new Exception('changing msg_qbytes needs root privileges');

return $this->set_status('msg_qbytes', $size);

}

/**

* 判断一个队列是否存在

* @param $key

* @return bool

*/

public function queue_exists($key)

{

return msg_queue_exists($key);

}

/**

* 检查修改队列状态的权限

* @param $key

* @throws Exception

*/

private function check_set_privilege($key)

{

$privilege_field = array('msg_perm.uid', 'msg_perm.gid', 'msg_perm.mode');

if (!in_array($key, $privilege_field)) {

throw new Exception('you can only change msg_perm.uid, msg_perm.gid, msg_perm.mode and msg_qbytes. And msg_qbytes needs root privileges');

}

}

}

调用方式如下:

写入队列:<?php

/**

* Created by PhpStorm.

* User: huyanping

* Date: 14-8-22

* Time: 下午12:13

*/

define('TEST_ROOT', dirname(__FILE__));

require TEST_ROOT . '/../core/IMessageQueue.interface.php';

require TEST_ROOT . '/../core/SystemVMessageQueue.class.php';

try{

$messageQueue = new SystemVMessageQueue(1, dirname(__FILE__));

while(true){

var_dump($messageQueue->put(mt_rand(0, 1000)));

echo $messageQueue->size() . PHP_EOL;

sleep(1);

}

}catch(Exception $e){

echo $e->getMessage();

}

读取队列:<?php

/**

* Created by PhpStorm.

* User: huyanping

* Date: 14-8-22

* Time: 下午12:13

*/

define('TEST_ROOT', dirname(__FILE__));

require TEST_ROOT . '/../core/IMessageQueue.interface.php';

require TEST_ROOT . '/../core/SystemVMessageQueue.class.php';

try{

$messageQueue = new SystemVMessageQueue(1, dirname(__FILE__));

while(true){

var_dump($messageQueue->get());

sleep(1);

}

}catch(Exception $e){

echo $e->getMessage();

}

删除队列:<?php

/**

* Created by PhpStorm.

* User: Administrator

* Date: 14-8-22

* Time: 下午2:35

*/

define('TEST_ROOT', dirname(__FILE__));

require TEST_ROOT . '/../core/IMessageQueue.interface.php';

require TEST_ROOT . '/../core/SystemVMessageQueue.class.php';

try{

$messageQueue = new SystemVMessageQueue(1, dirname(__FILE__));

var_dump($messageQueue->queue_remove());

}catch(Exception $e){

echo $e->getMessage();

}

原创文章,转载请注明: 转载自始终不够

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值