Docker环境下PHP安装Mosquitto扩展,并配合Swoole测试。PHP对MQTT的使用——完整教程
最近在工作中碰到物联网相关的项目,所以为了帮助理解MQTT,直接撸一个Demo。至于为啥选择MQTT大家可以自行搜索做拓展了解。补充一点:网上MQTT服务还是挺多的,选择Mosquitto入手的原因是因为本身php就有Mosquitto的扩展。并且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 服务已经成功部署
点击查看代码
Mosquitto 主目录 |-Dockerfile |-docker-compose.yml |-mqtt_pub.php 发布demo |-mqtt_sub.php 订阅demo
点击查看代码
<?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
效果如下所示:
大功告成!!!