Docker环境下PHP安装Mosquitto扩展,并配合Swoole测试。PHP对MQTT的使用——完整教程

最近在工作中碰到物联网相关的项目,所以为了帮助理解MQTT,直接撸一个Demo。至于为啥选择MQTT大家可以自行搜索做拓展了解。补充一点:网上MQTT服务还是挺多的,选择Mosquitto入手的原因是因为本身php就有Mosquitto的扩展。并且Mosquitto服务也是支持多语言的,所以对于协同开发来说还是比较友好的。以下教程全程在docker环境中部署,所以无关操作系统

 

1、首先我们需要一台Mosquitto的消息代理服务,这里我直接选择使用docker的官方镜像

 

按照他官方镜像的参考文档,我们会需要有配置、持久存储和日志文件。那么我选择的目录结构如下

点击查看代码
Mosquitto	主目录
|-data			   持久化数据目录
|-log			   日志目录
|-mosquitto.conf   	   配置文件	
|-pwdfile		   密码文件

 

接下来我们先编写 mosquitto 的配置文件也就是上面的 mosquitto.conf

点击查看代码
# =================================================================
# General configuration
# =================================================================

# 客户端心跳的间隔时间
#retry_interval 20

# 系统状态的刷新时间
#sys_interval 10

# 系统资源的回收时间,0表示尽快处理
#store_clean_interval 10

# 服务进程的PID
#pid_file /var/run/mosquitto.pid

# 服务进程的系统用户
#user mosquitto

# 客户端心跳消息的最大并发数
#max_inflight_messages 10

# 客户端心跳消息缓存队列
#max_queued_messages 100

# 用于设置客户端长连接的过期时间,默认永不过期
#persistent_client_expiration

# =================================================================
# Default listener
# =================================================================

# 服务绑定的IP地址
#bind_address

# 服务绑定的端口号,老版本的mosquitto使用的port设置端口,新版改用listener
#port 1883

#新版使用的端口配置
listener 1883 0.0.0.0

# 允许的最大连接数,-1表示没有限制
max_connections 1000

# cafile:CA证书文件
# capath:CA证书目录
# certfile:PEM证书文件
# keyfile:PEM密钥文件
#cafile
#capath
#certfile
#keyfile

# 必须提供证书以保证数据安全性
#require_certificate false

# 若require_certificate值为true,use_identity_as_username也必须为true
#use_identity_as_username false

# 启用PSK(Pre-shared-key)支持
#psk_hint

# SSL/TSL加密算法,可以使用“openssl ciphers”命令获取
# as the output of that command.
#ciphers

# =================================================================
# Persistence
# =================================================================

# 消息自动保存的间隔时间
#autosave_interval 1800

# 消息自动保存功能的开关
#autosave_on_changes false

# 持久化功能的开关
persistence true

# 持久化DB文件
#persistence_file mosquitto.db

# 持久化DB文件目录
persistence_location /mosquitto/data

# =================================================================
# Logging
# =================================================================

# 4种日志模式:stdout、stderr、syslog、topic
# none 则表示不记日志,此配置可以提升些许性能
log_dest file /mosquitto/log/mosquitto.log

# 选择日志的级别(可设置多项)
log_type error
log_type warning
log_type notice
log_type information

# 是否记录客户端连接信息
#connection_messages true

# 是否记录日志时间
log_timestamp true

# =================================================================
# Security
# =================================================================

# 客户端ID的前缀限制,可用于保证安全性
#clientid_prefixes

# 允许匿名用户
allow_anonymous false

# 用户/密码文件,默认格式:username:password
password_file /mosquitto/pwdfile

# PSK格式密码文件,默认格式:identity:key
#psk_file

# pattern write sensor/%u/data
# ACL权限配置,常用语法如下:
# 用户限制:user <username>
# 话题限制:topic [read|write] <topic>
# 正则限制:pattern write sensor/%u/data
#acl_file

# =================================================================
# Bridges
# =================================================================

# 允许服务之间使用“桥接”模式(可用于分布式部署)
#connection <name>
#address <host>[:<port>]
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]

# 设置桥接的客户端ID
#clientid

# 桥接断开时,是否清除远程服务器中的消息
#cleansession false

# 是否发布桥接的状态信息
#notifications true

# 设置桥接模式下,消息将会发布到的话题地址
# $SYS/broker/connection/<clientid>/state
#notification_topic

# 设置桥接的keepalive数值
#keepalive_interval 60

# 桥接模式,目前有三种:automatic、lazy、once
#start_type automatic

# 桥接模式automatic的超时时间
#restart_timeout 30

# 桥接模式lazy的超时时间
#idle_timeout 60

# 桥接客户端的用户名
#username

# 桥接客户端的密码
#password

# bridge_cafile:桥接客户端的CA证书文件
# bridge_capath:桥接客户端的CA证书目录
# bridge_certfile:桥接客户端的PEM证书文件
# bridge_keyfile:桥接客户端的PEM密钥文件
#bridge_cafile
#bridge_capath
#bridge_certfile
#bridge_keyfile

# 自己的配置可以放到以下目录中
#include_dir /etc/mosquitto/conf.d

 

然后咱们直接把 mosquitto 容器服务起起来就行了 

点击查看代码
# 拉取 mosquitto 官方镜像
docker pull eclipse-mosquitto

# 创建并运行容器
docker run -itd --name mosquitto -p 1883:1883 -v mosquitto.conf:/mosquitto/mosquitto.conf -v ./data:/mosquitto/data -v ./log:/mosquitto/log eclipse-mosquitto

 

 到这一步还没完,我们还需要给 mosquitto 服务配置用户名密码。首先我们在 pwdfile 写入一对用户名密钥对格式如下

点击查看代码
# 用户名:密码
admin:123456

 

配置完成之后我们需要进入到容器里面执行一段密码文件的加密指令,否则 mosquitto 服务将无法认证该密钥对(如果是使用 Dockerfile 创建的容器可以直接在编写 Dockerfile 完成该步骤) 

点击查看代码
# 进入 docker 容器
docker exec -it [容器id] sh

# 执行加密
mosquitto_passwd -U /mosquitto/mosquitto.conf

 

然后我们就可以看到 pwdfile 文件里面的内容已经被 hash 过了的密文,接着重启 mosquitto 容器即可。此时 mosquitto 服务已经成功部署

 

 

2、接下来咱们部署PHP环境,并且简单使用一下 mosquitto 服务

 

这里介绍一下我的目录结构

点击查看代码
Mosquitto	主目录
|-Dockerfile	
|-docker-compose.yml
|-mqtt_pub.php	发布demo	
|-mqtt_sub.php	订阅demo

 

下面我们编写一下 mqtt_pub.php 和 mqtt_sub.php 文件, mosquitto 的php文档可以参考:mosquitto的php文档

mqtt_pub.php

点击查看代码
<?php
define('BASE_PATH', __DIR__);

use Swoole\Coroutine;
use Swoole\Runtime;

Runtime::enableCoroutine();

$client = [];

try {

    for ($i = 0; $i < 10; $i++) {
        $client[$i] = new Mosquitto\Client();
        $client[$i]->setCredentials('admin', '123456');
        $client[$i]->setWill('dead', 'I am offline ', 1, false);
        $client[$i]->connect('127.0.0.1', 1883, 60);
    }

    foreach ($client as $key => $value) {
        Coroutine::create(function () use ($key, $value) {
            //usleep(rand(0,9999));
            var_dump($key);
            $value->onConnect(function (int $rc, string $message) {
                var_dump($rc, $message);
            });

            $value->onDisconnect(function (int $rc) {
                var_dump($rc);
            });

            while (true) {
                $value->loop();
                $value->publish('myMqtt', (string)$key, 1);
                $value->loop();
                usleep(rand(100, 999));
            }
        });
    }

} catch (\Mosquitto\Exception $exception) {
    var_dump('err', $exception->getMessage());
}

 

mqtt_sub.php

点击查看代码
<?php
define('BASE_PATH', __DIR__);

try {
    $client = new Mosquitto\Client();
    $client->setCredentials('admin', '123456');
    $client->connect('127.0.0.1', 1883, 60);

    $client->onConnect(function (int $rc, string $message) {
        var_dump($rc, $message);
    });

    $client->onDisconnect(function (int $rc) {
        var_dump($rc);
    });

    $client->subscribe('myMqtt', 2);
    $client->subscribe('dead', 1);

    $client->onMessage(function ($data) {
        /** @var Mosquitto\Message $data */
        var_dump($data->payload);
    });

    $client->loopForever();
}catch (\Mosquitto\Exception $exception) {
    var_dump('err',$exception->getMessage());
}

 

接下来是PHP环境搭建,这里我采用的 swoole 的官方镜像,还需要安装 php 的 mosquitto 扩展,所以这里写了一份Dockerfile

点击查看代码
FROM phpswoole/swoole:4.7.1-php7.4

LABEL maintainer="Taurus12C"

ARG timezone

ENV TIMEZONE=${timezone:-"Asia/Shanghai"}

RUN ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
    && echo "${TIMEZONE}" > /etc/timezone \
    && sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
    && apt-get clean \
    && apt-get update -y \
    && apt-get upgrade -y \
    && apt-get install libmosquitto-dev -y \
    && pecl install Mosquitto-alpha \
    && docker-php-ext-enable mosquitto

WORKDIR /opt/www

COPY . /opt/www

 

接下来就是使用上面的镜像文件启动一个容器,这里可以用 docker build 之后再 docker run,或者直接使用 docker-compose 我这里使用的后者

点击查看代码
version: "3.5"
services:
  demo:
    build: .
    restart: always
    container_name: demo
    networks:
      - test
    volumes:
      - ./:/opt/www
networks:
  test:
    external: true
    #我这里用了一个名为test的docker网络,注意自己使用的时候要先执行 docker network create test 一下

 

然后直接启动容器,打开两个 CLI 窗口进入容器执行php代码,查看效果

点击查看代码
docker-compose up -d

 

第一个 CLI 窗口

点击查看代码
# 进入容器
docker exec -it [容器id] sh

# 执行订阅代码文件
php mqtt_sub.php

 

第二个 CLI 窗口

点击查看代码
# 进入容器
docker exec -it [容器id] sh

# 执行订阅代码文件
php mqtt_pub.php

 

效果如下所示:

     

 

大功告成!!!

 

posted on 2021-11-15 14:31  Taurus12C  阅读(900)  评论(0编辑  收藏  举报

导航