Environment
- Lumen (5.5.2) (Laravel Components 5.5.*)
- Laravel(5.5.*)
- RabbitMQ
Process
前提
Artisan 命令
- 使用 Artisan 命令,创建作为消费的 worker 脚本。
php artisan make:command MoreRequestLogMQConsume
Laravel 消费者脚本
- 配置文件还是基于 Laravel 拓展包 mookofe/tail 的 config/tail-settings.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Mookofe\Tail\Facades\Tail;
use Illuminate\Support\Facades\DB;
use PhpAmqpLib\Connection\AMQPStreamConnection;
class MoreRequestLogMQConsume extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'mq:request:log:consume';
/**
* The console command description.
*
* @var string
*/
protected $description = 'mq consume request log';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$connection = new AMQPStreamConnection(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.host'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.port', '5672'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.username'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.password'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.vhost', '/')
);
$channel = $connection->channel();
$channel->exchange_declare(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange', ''),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange_type'),
false, false, false);
$channel->queue_declare(config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.queue_name'), false, true, false, false);
$channel->queue_bind(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.queue_name'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange', ''));
$callback = function ($msg) {
DB::connection('cappu')
->select
('
CREATE TABLE
IF
NOT EXISTS `m_interface_log_' . date('Ym') . '` (
`id` INT ( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT,
`path` VARCHAR ( 255 ) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT "" COMMENT "路径",
`method` VARCHAR ( 64 ) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT "" COMMENT "方法",
`ip` VARCHAR ( 32 ) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT "" COMMENT "客户端IP",
`request_header` text COLLATE utf8mb4_unicode_ci,
`request_body` text COLLATE utf8mb4_unicode_ci,
`response_header` text COLLATE utf8mb4_unicode_ci,
`response_body` text COLLATE utf8mb4_unicode_ci,
`created_at` TIMESTAMP NOT NULL DEFAULT "0000-00-00 00:00:00",
`updated_at` TIMESTAMP NOT NULL DEFAULT "0000-00-00 00:00:00" ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY ( `id` ) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = COMPACT;
');
DB::connection('cappu')
->table('m_interface_log_' . date('Ym'))
->insert(json_decode($msg->body, true));
// Log::info('MoreRequestLogMQConsume:' . json_encode($msg));
//$channel->basic_consume(),$no_ack 参数设置为 false ,必须写此段代码响应,其值为 true,则不必写。
$msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
};
$channel->basic_qos(null, config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.prefetch_count', 1), null);
$channel->basic_consume(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.queue_name'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.consumer_tag', ''),
false, false, false, false, $callback
);
while (count($channel->callbacks)) {
$channel->wait();
}
$channel->close();
$connection->close();
}
}
- 消费者接收的信息体「$msg」
{
"body":"{"path":"v2\/users","method":"GET","request_body":"[]","created_at":"2019-07-17 16:04:34"}",//生产者传递的数据(此处系Json数据)
"body_size":1614,
"is_truncated":false,
"content_encoding":null,
"delivery_info":{
"channel":{
"callbacks":{
"more.request.log.producer":{
}
}
},
"consumer_tag":"more.request.log.producer",
"delivery_tag":"1",
"redelivered":true,
"exchange":"request.log",
"routing_key":""
}
}
- 运行脚本
nohup php artisan mq:request:log:consume >> mq-request-consume.log 2>&1 &
- 查看启动的进程
ps -aux | grep php
Lumen 推送生产者消息
- 配置文件还是基于拓展包 mookofe/tail 的 config/tail-settings.php
<?php
namespace App\Http\Middleware;
use Closure;
use Validator;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
class InterfaceLog
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
if (env('INTERFACE_LOG_SWITCH', 0) && $request->path() != 'v2/anchors') {
if (! empty($_SERVER["HTTP_CLIENT_IP"])) {
$ip = $_SERVER["HTTP_CLIENT_IP"];
} elseif (! empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} elseif(! empty($_SERVER["REMOTE_ADDR"])) {
$ip = $_SERVER["REMOTE_ADDR"];
} else {
$ip = '';
}
$connection = new AMQPStreamConnection(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.host'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.port', '5672'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.username'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.password'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.vhost', '/')
);
$channel = $connection->channel();
$channel->exchange_declare(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange', ''),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange_type'),
false, false, false);
$channel->queue_declare(config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.queue_name'), false, true, false, false);
//在RabbitMQ PHP版Gitbook使用说明书里面,生产者代码示例没有这种写法,但是事实上,$channel->queue_bind()函数完成可以在此使用。如果没有这样写,生产者先启动,可能会造成数据丢失,因为没有存入到相应的队列。
$channel->queue_bind(
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.queue_name'),
config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange', ''),
);
$msg = new AMQPMessage(json_encode([
'path' => $request->path(),
'method' => $request->method(),
'ip' => $ip,
'request_header' => json_encode($request->header(),JSON_UNESCAPED_UNICODE),
'request_body' => json_encode($request->all(),JSON_UNESCAPED_UNICODE),
'response_header' => json_encode($response->headers,JSON_UNESCAPED_UNICODE),
'response_body' => json_encode($response->original,JSON_UNESCAPED_UNICODE),
'created_at' => date('Y-m-d H:i:s')
]),
array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT)
);
$channel->basic_publish($msg, config('tail-settings.connections.' . env('MQ_REQUEST_LOG_CONNECTION') . '.exchange', ''));
$channel->close();
$connection->close();
}
}
}
Conclusion
不同的版本,对应的文件路径会有些出入,以上仅供参考,请君灵活处理。
转载本文,请注明出处、作者。