如何在codeigniter中从rabbitmq php consumer的回调中调用模型?

时间:2013-04-22 13:20:48

标签: php mysql codeigniter rabbitmq publish-subscribe

我开发了一个Android应用程序,它可以订阅队列,也可以发布到其他队列。它一次向两个不同的队列发布相同的消息,其中一个队列名为" Queue"现在从appfog实例我需要订阅" Queue"并使用消息并将它们插入mysql db。

我使用codeigniter为上述目的创建了一个php独立应用程序。由于某种原因,工作者应用程序失去了与rabbitmq的连接。我想知道最好的方法。 appfog上的工作者应用程序如何才能维持应用程序的重启。

我需要用什么来解决上述问题。

我认为问题不在于rabbitmq连接。它是与mysql插入相关的代码。我检查了我的应用程序的崩溃日志,错误是" Mysql消失了#34;。一个php rabbitmq使用者的例子有接收消息和register_shutdown的回调。在接收回调我不能使用$ this代码点火器,因为它超出范围,我使用get_instance()。我不知道如何从rabbitmq客户端调用一个方法接收回调函数

控制器是

<?php

if (!defined('BASEPATH'))
  exit('No direct script access allowed');

include(__DIR__ . '/php-amqplib/config.php');

use PhpAmqpLib\Connection\AMQPConnection;

class Welcome extends CI_Controller {

public function __construct() {
    parent::__construct();
}

public function index() {
    //connect to rabbitmq and consume messages
    //insert messages to mysql
    //$this->messages = array();
    $exchange = "router";
    $queue = "abbiya";

    $conn = new AMQPConnection(HOST, PORT, USER, PASS, VHOST);
    $ch = $conn->channel();

    /*
      name: $queue
      passive: false
      durable: true // the queue will survive server restarts
      exclusive: false // the queue can be accessed in other channels
      auto_delete: false //the queue won't be deleted once the channel is closed.
     */
    $ch->queue_declare($queue, false, true, false, false);

    $ch->queue_bind($queue, $exchange, $queue);

    /*
      queue: Queue from where to get the messages
      consumer_tag: Consumer identifier
      no_local: Don't receive messages published by this consumer.
      no_ack: Tells the server if the consumer will acknowledge the messages.
      exclusive: Request exclusive consumer access, meaning only this consumer can access the queue
      nowait:
      callback: A PHP Callback
     */
    $consumer_tag = "abbiya";

    $ch->basic_recover(true);
    $ch->basic_consume($queue, $consumer_tag, false, false, false, false, function($msg) {
                $message_body = json_decode($msg->body);
                $msg->delivery_info['channel']->
                        basic_ack($msg->delivery_info['delivery_tag']);

                // Send a message with the string "quit" to cancel the consumer.
                if ($msg->body === 'quit') {
                    $msg->delivery_info['channel']->
                            basic_cancel($msg->delivery_info['consumer_tag']);
                }
                $data = array(
                    'sender_id' => $message_body->r,
                    'receiver_id' => $message_body->s,
                    'message_content' => $message_body->m,
                    // 'sent_time' => $message_body->t,
                    'status' => 0
                );
                $ci =& get_instance();
                $ci->Message_model->newMessage($data);
            }
    );

    // Loop as long as the channel has callbacks registered
    while (count($ch->callbacks)) {
        $ch->wait();
    }

    register_shutdown_function(function() use ($ch, $conn) {
                $ch->close();
                $conn->close();
                $this->index();
            }
    );
}

}

/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */

1 个答案:

答案 0 :(得分:2)

首先,我必须说使用CodeIgniter创建一个消费者并且php可能不是一个好主意,除非你添加这样的东西

    if( !$this->input->is_cli_request() ){
        show_404(); // So they dont know this is an actual script
        die();
    }

从命令行运行nohup或daemonize it。

您可以使用codeigniter的$ this-&gt; db-&gt; reconnect();正常重新连接数据库。

我们已经使用php和CI为测试目的做了一些消费者。 我们将回调函数放入一个帮助程序中,并添加了一种让call_back函数返回false的方法,以便消费者在完成后停止侦听。

对于我们的生产系统,我们使用python,java或camel消费者,这些消费者更适合这项工作。