这段时间看了不少的资料,主要是时间太多了,想学的也太多了,就什么都看了一下
现在就接着总结自己的得到的东西,顺便梳理一下自己的知识面
之前说过RabbitMQ的基本构成,今天把代码列出来 PHP 和GO版本两版
PHP 是基于Laravel的框架做的,怎么说的那,因为最近也在看swoole 感觉只要分服务端和客户端的 最好的还是脚本 或者 像用GO去写一个服务,在服务器起一个进程,通过设置监听来判断业务的执行
<?php
namespace App\Http\Controllers\Mq;
use AMQPChannel;
use AMQPConnection;
use AMQPExchange;
use AMQPQueue;
use App\Http\Controllers\Controller;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
class MqtestController extends Controller
{
public $channel; //信道
public $connection; //连接
public $exchange; //交换机
public $queue; //队列
public $data;
public function __construct()
{//first 建立连接
$this->connection = new AMQPConnection([
'host' => '192.168.1.139', //本地机器的ip
'port' => 5672 //端口号
]);
if (!$this->connection->connect()) {
throw new \mysql_xdevapi\Exception('RabbitMq创建连接失败');
}
}
/**
* 创建生产者
* @module
* @controller
* @throws \AMQPChannelException
* @throws \AMQPConnectionException
* @throws \AMQPExchangeException
* @throws \AMQPQueueException
*/
public function setGoodsProductMQ()
{
// second创建信道
$this->channel = new AMQPChannel($this->connection);
//third 创建交换机
$this->exchange = new AMQPExchange($this->channel);
//设置交换机名称
$this->exchange->setName('newex');
//设置交换机类型
$this->exchange->setType(AMQP_EX_TYPE_DIRECT);
//设置交换机标志 durabl 持久化设置 1(非持久化) 2
$this->exchange->setFlags(AMQP_DURABLE);
$this->exchange->declareExchange();
$data = [
'id' => 88,
'name' => '小脑斧'
];
$data = json_encode($data);
// 发布消息
$this->exchange->publish($data, 'self_define_routing_key');
}
public function setQue()
{
// second创建信道
$this->channel = new AMQPChannel($this->connection);
//fourth 创建队列并绑定交换机
$this->queue = new AMQPQueue($this->channel);
//设置队列名称
$this->queue->setName('newqu');
//设置队列性质(标志)
$this->queue->setFlags(AMQP_DURABLE);
$this->queue->declareQueue();
}
public function setConsumer()
{
$exchangeName = 'newex';
$queueName = 'newqu';
$channel = new AMQPChannel($this->connection);
// 通过信道创建交换器对象
$exchange = new AMQPExchange($channel);
// 声明自己监听哪个队列
$queue = new AMQPQueue($channel);
// 设置交换器名称
$exchange->setName($exchangeName);
$queue->setName($queueName);
//设置队列性质(标志)
$queue->setFlags(AMQP_DURABLE);
//队列解析
$queue->declareQueue();
//绑定监听
$queue->bind($exchangeName, 'self_define_routing_key');
$queue->consume(
function ($envelope, $queue) {
$msg = $envelope->getBody();
if(!empty($msg)){
echo $msg . "\n"; //处理消息
$queue->ack($envelope->getDeliveryTag());
}else{
print_r("发送完成");
exit;
}
}); //阻塞监听
}
}
怎么说呢,AMQP是一种协议性的,RabbitMQ实际上就一个协议的实现过程,学过网络的或者socket的都知道TCP,UDP,HTTP等常见协议,当客户端和服务端都遵循一种协议就可以相互通信双向获取信息数据,好吧这里可能是废话,但是要提到的关键点就是 协议就一种规定,或者建立通信一种规范模型,像是你吃饭,张嘴,吞咽,这样的流程,好吧可能又是废话。
上面的代码是生产者消费者的代码 ,生产者可以是服务端自动生产,也可以是用户手动产生,消费者同样,按照调用情况和使用需求来设置
基本的流程就是
1.建立 AMQP协议连接,确认连接连接成功
2.连接成功了那就是创建 交换器和队列了
3.交换器和队列这两个存储类型的对象都有了,那么就要将他们连起来了,那就是channel(信道)的作用了
按照上面的流程,不论你是
(用户调用的生产,服务器的自动生产当然就不用再连接服务器了,直接脚本或已有服务就运行出来拉)
生产 用户 --------->连接服务器-----xinxi---->交换机(Exchange)------带着xinxi的信道------->队列(服务端)
还是反过来的 消费 队列 -------->用户
基本上的mq通信就简单的完成了,当然实际的生产环境中的要是这样做那就祝你好运了
下面的是GO的代码,对于一些性质类的知识,我还是在后面再一个一个的详说吧
conn,err := amqp.Dial(config.RMQADDR) //连接地址
failOnError(err,"Failed to connect to RabbitMQ")
defer conn.Close()
var wg sync.WaitGroup //阻塞等待所有任务完成之后再继续执行。
wg.Add(5) //添加任务
for routine :=0; routine < 5; routine++ {
//创建新的并发
go func(routineNum int) {
ch,err := conn.Channel()
failOnError(err,"Failed to open a channel")
defer ch.Close()
//创建队列
q,err := ch.QueueDeclare(
config.QUEUENAME,//队列名称
true,
false,
false,
false,
nil,
)
failOnError(err,"Failed to declare a queue")
for i:=0;i<500;i++{
msgBody := fmt.Sprintf("Message_%d_%d",routineNum,i)
//发布消息
err = ch.Publish(
"", //exchange
q.Name, //routing key
false,
false,
amqp.Publishing{
DeliveryMode: amqp.Persistent, //Msg set as persistent
ContentType: "text/plain",
Body: []byte(msgBody),
})
log.Printf("[x] Sent %s",msgBody)
failOnError(err,"Failed to publish a message")
}
wg.Done() //任务完成-1
}(routine)