--
MQTT broker
Broker 幾乎都是 Erlang 的天下
後續考量 MySQL 身份認證、SSL、平台支援、ACL 訂閱限制,最後選擇 EMQ X
--
EMQ X
不得不說,大陸的軟體就是好用,設想的較為周全,文件也齊全,平台支援性也完整
CentOS 7
1 2 3 |
# wget https://www.emqx.io/downloads/broker/v4.2.3/emqx-centos7-4.2.3-x86_64.rpm # rpm -ivh emqx-centos7-4.2.3-x86_64.rpm # emqx start |
Ubuntu 20
1 2 3 |
# wget https://www.emqx.io/cn/downloads/broker/v4.2.2/emqx-ubuntu20.04-4.2.2-x86_64.deb # dpkg -i emqx-ubuntu20.04-4.2.2-x86_64.deb # emqx start |
--
VerneMQ
CentOS 7
下載安裝後不要傻傻的按照官方的說法直接啟動服務,那是不會成功的,還要先設定設定檔才行
1 2 3 4 5 6 7 8 9 10 11 12 13 |
-- Unit vernemq.service has begun starting up. Nov 15 14:39:18 hoyoserver vernemq[3427]: Before you can continue, the product license Nov 15 14:39:18 hoyoserver vernemq[3427]: must be accepted. The license can be viewed at Nov 15 14:39:18 hoyoserver vernemq[3427]: https://vernemq.com/end-user-license-agreement Nov 15 14:39:18 hoyoserver vernemq[3427]: If you do not accept this license you will Nov 15 14:39:18 hoyoserver vernemq[3427]: not be able to use VerneMQ. Nov 15 14:39:18 hoyoserver vernemq[3427]: Accepting the product license will modify the Nov 15 14:39:18 hoyoserver vernemq[3427]: VerneMQ config file Nov 15 14:39:18 hoyoserver vernemq[3427]: /etc/vernemq/vernemq.conf Nov 15 14:39:18 hoyoserver systemd[1]: vernemq.service: control process exited, code=exited status=2 Nov 15 14:39:18 hoyoserver vernemq[3427]: setting the "accept_eula" config to "yes". Nov 15 14:39:18 hoyoserver vernemq[3427]: Product license not accepted. Stopping. Nov 15 14:39:18 hoyoserver systemd[1]: Failed to start VerneMQ Server. |
1 |
# vi /etc/vernemq/vernemq.conf |
1 2 |
accept_eula = yes listener.tcp.default = 0.0.0.0:1883 |
Ubuntu 20 - Docker
使用 dpkg 安裝 deb ,出現 libss 版本不符錯誤,目前找不到解決方法,改採 Docker 方式使用
1 |
# docker run -p 1883:1883 -p 8888:8888 -e "DOCKER_VERNEMQ_ACCEPT_EULA=yes" -e "DOCKER_VERNEMQ_ALLOW_ANONYMOUS=on" --name vernemq1 -d vernemq/vernemq |
使用 netstat 查詢轉址無法判斷,直接測試使用即可
開機啟動
1 |
# docker update --restart=always <CONTAINER ID> |
Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
FROM debian:stretch-slim RUN apt-get update && \ apt-get -y install bash procps openssl iproute2 curl jq libsnappy-dev net-tools && \ rm -rf /var/lib/apt/lists/* && \ addgroup --gid 10000 vernemq && \ adduser --uid 10000 --system --ingroup vernemq --home /vernemq --disabled-password vernemq WORKDIR /vernemq # Defaults ENV DOCKER_VERNEMQ_KUBERNETES_LABEL_SELECTOR="app=vernemq" \ DOCKER_VERNEMQ_LOG__CONSOLE=console \ PATH="/vernemq/bin:$PATH" \ VERNEMQ_VERSION="1.11.0" COPY --chown=10000:10000 bin/vernemq.sh /usr/sbin/start_vernemq COPY --chown=10000:10000 files/vm.args /vernemq/etc/vm.args ADD https://github.com/vernemq/vernemq/releases/download/$VERNEMQ_VERSION/vernemq-$VERNEMQ_VERSION.stretch.tar.gz /tmp RUN tar -xzvf /tmp/vernemq-$VERNEMQ_VERSION.stretch.tar.gz && \ rm /tmp/vernemq-$VERNEMQ_VERSION.stretch.tar.gz && \ chown -R 10000:10000 /vernemq && \ ln -s /vernemq/etc /etc/vernemq && \ ln -s /vernemq/data /var/lib/vernemq && \ ln -s /vernemq/log /var/log/vernemq # Ports # 1883 MQTT # 8883 MQTT/SSL # 8080 MQTT WebSockets # 44053 VerneMQ Message Distribution # 4369 EPMD - Erlang Port Mapper Daemon # 8888 Prometheus Metrics # 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 Specific Distributed Erlang Port Range EXPOSE 1883 8883 8080 44053 4369 8888 \ 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 VOLUME ["/vernemq/log", "/vernemq/data", "/vernemq/etc"] HEALTHCHECK CMD vernemq ping | grep -q pong USER vernemq CMD ["start_vernemq"] |
- 啟動自動執行 /usr/sbin/start_vernemq
start_vernemq
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
#!/usr/bin/env bash NET_INTERFACE=$(route | grep '^default' | grep -o '[^ ]*$') NET_INTERFACE=${DOCKER_NET_INTERFACE:-${NET_INTERFACE}} IP_ADDRESS=$(ip -4 addr show ${NET_INTERFACE} | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed -e "s/^[[:space:]]*//" | head -n 1) IP_ADDRESS=${DOCKER_IP_ADDRESS:-${IP_ADDRESS}} # Ensure the Erlang node name is set correctly if env | grep "DOCKER_VERNEMQ_NODENAME" -q; then sed -i.bak -r "s/-name VerneMQ@.+/-name VerneMQ@${DOCKER_VERNEMQ_NODENAME}/" /vernemq/etc/vm.args else if [ -n "$DOCKER_VERNEMQ_SWARM" ]; then NODENAME=$(hostname -i) sed -i.bak -r "s/VerneMQ@.+/VerneMQ@${NODENAME}/" /etc/vernemq/vm.args else sed -i.bak -r "s/-name VerneMQ@.+/-name VerneMQ@${IP_ADDRESS}/" /vernemq/etc/vm.args fi fi if env | grep "DOCKER_VERNEMQ_DISCOVERY_NODE" -q; then discovery_node=$DOCKER_VERNEMQ_DISCOVERY_NODE if [ -n "$DOCKER_VERNEMQ_SWARM" ]; then tmp='' while [[ -z "$tmp" ]]; do tmp=$(getent hosts tasks.$discovery_node | awk '{print $1}' | head -n 1) sleep 1 done discovery_node=$tmp fi if [ -n "$DOCKER_VERNEMQ_COMPOSE" ]; then tmp='' while [[ -z "$tmp" ]]; do tmp=$(getent hosts $discovery_node | awk '{print $1}' | head -n 1) sleep 1 done discovery_node=$tmp fi sed -i.bak -r "/-eval.+/d" /vernemq/etc/vm.args echo "-eval \"vmq_server_cmd:node_join('VerneMQ@$discovery_node')\"" >> /vernemq/etc/vm.args fi # If you encounter "SSL certification error (subject name does not match the host name)", you may try to set DOCKER_VERNEMQ_KUBERNETES_INSECURE to "1". insecure="" if env | grep "DOCKER_VERNEMQ_KUBERNETES_INSECURE" -q; then insecure="--insecure" fi if env | grep "DOCKER_VERNEMQ_DISCOVERY_KUBERNETES" -q; then DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME=${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME:-cluster.local} # Let's get the namespace if it isn't set DOCKER_VERNEMQ_KUBERNETES_NAMESPACE=${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE:-`cat /var/run/secrets/kubernetes.io/serviceaccount/namespace`} # Let's set our nodename correctly VERNEMQ_KUBERNETES_SUBDOMAIN=${DOCKER_VERNEMQ_KUBERNETES_SUBDOMAIN:-$(curl -X GET $insecure --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes.default.svc.$DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME/api/v1/namespaces/$DOCKER_VERNEMQ_KUBERNETES_NAMESPACE/pods?labelSelector=$DOCKER_VERNEMQ_KUBERNETES_LABEL_SELECTOR -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" | jq '.items[0].spec.subdomain' | sed 's/"//g' | tr '\n' '\0')} if [ $VERNEMQ_KUBERNETES_SUBDOMAIN == "null" ]; then VERNEMQ_KUBERNETES_HOSTNAME=${MY_POD_NAME}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME} else VERNEMQ_KUBERNETES_HOSTNAME=${MY_POD_NAME}.${VERNEMQ_KUBERNETES_SUBDOMAIN}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME} fi sed -i.bak -r "s/VerneMQ@.+/VerneMQ@${VERNEMQ_KUBERNETES_HOSTNAME}/" /vernemq/etc/vm.args # Hack into K8S DNS resolution (temporarily) kube_pod_names=$(curl -X GET $insecure --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://kubernetes.default.svc.$DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME/api/v1/namespaces/$DOCKER_VERNEMQ_KUBERNETES_NAMESPACE/pods?labelSelector=$DOCKER_VERNEMQ_KUBERNETES_LABEL_SELECTOR -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" | jq '.items[].spec.hostname' | sed 's/"//g' | tr '\n' ' ') for kube_pod_name in $kube_pod_names; do if [ $kube_pod_name == "null" ] then echo "Kubernetes discovery selected, but no pods found. Maybe we're the first?" echo "Anyway, we won't attempt to join any cluster." break fi if [ $kube_pod_name != $MY_POD_NAME ] then echo "Will join an existing Kubernetes cluster with discovery node at ${kube_pod_name}.${VERNEMQ_KUBERNETES_SUBDOMAIN}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME}" echo "-eval \"vmq_server_cmd:node_join('VerneMQ@${kube_pod_name}.${VERNEMQ_KUBERNETES_SUBDOMAIN}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME}')\"" >> /vernemq/etc/vm.args break fi done fi if [ -f /vernemq/etc/vernemq.conf.local ]; then cp /vernemq/etc/vernemq.conf.local /vernemq/etc/vernemq.conf sed -i -r "s/###IPADDRESS###/${IP_ADDRESS}/" /vernemq/etc/vernemq.conf else sed -i '/########## Start ##########/,/########## End ##########/d' /vernemq/etc/vernemq.conf echo "########## Start ##########" >> /vernemq/etc/vernemq.conf env | grep DOCKER_VERNEMQ | grep -v 'DISCOVERY_NODE\|KUBERNETES\|SWARM\|COMPOSE\|DOCKER_VERNEMQ_USER' | cut -c 16- | awk '{match($0,/^[A-Z0-9_]*/)}{print tolower(substr($0,RSTART,RLENGTH)) substr($0,RLENGTH+1)}' | sed 's/__/./g' >> /vernemq/etc/vernemq.conf users_are_set=$(env | grep DOCKER_VERNEMQ_USER) if [ ! -z "$users_are_set" ]; then echo "vmq_passwd.password_file = /vernemq/etc/vmq.passwd" >> /vernemq/etc/vernemq.conf touch /vernemq/etc/vmq.passwd fi for vernemq_user in $(env | grep DOCKER_VERNEMQ_USER); do username=$(echo $vernemq_user | awk -F '=' '{ print $1 }' | sed 's/DOCKER_VERNEMQ_USER_//g' | tr '[:upper:]' '[:lower:]') password=$(echo $vernemq_user | awk -F '=' '{ print $2 }') /vernemq/bin/vmq-passwd /vernemq/etc/vmq.passwd $username <<EOF $password $password EOF done if [ -z "$DOCKER_VERNEMQ_ERLANG__DISTRIBUTION__PORT_RANGE__MINIMUM" ]; then echo "erlang.distribution.port_range.minimum = 9100" >> /vernemq/etc/vernemq.conf fi if [ -z "$DOCKER_VERNEMQ_ERLANG__DISTRIBUTION__PORT_RANGE__MAXIMUM" ]; then echo "erlang.distribution.port_range.maximum = 9109" >> /vernemq/etc/vernemq.conf fi if [ -z "$DOCKER_VERNEMQ_LISTENER__TCP__DEFAULT" ]; then echo "listener.tcp.default = ${IP_ADDRESS}:1883" >> /vernemq/etc/vernemq.conf fi if [ -z "$DOCKER_VERNEMQ_LISTENER__WS__DEFAULT" ]; then echo "listener.ws.default = ${IP_ADDRESS}:8080" >> /vernemq/etc/vernemq.conf fi if [ -z "$DOCKER_VERNEMQ_LISTENER__VMQ__CLUSTERING" ]; then echo "listener.vmq.clustering = ${IP_ADDRESS}:44053" >> /vernemq/etc/vernemq.conf fi if [ -z "$DOCKER_VERNEMQ_LISTENER__HTTP__METRICS" ]; then echo "listener.http.metrics = ${IP_ADDRESS}:8888" >> /vernemq/etc/vernemq.conf fi echo "########## End ##########" >> /vernemq/etc/vernemq.conf fi # Check configuration file /vernemq/bin/vernemq config generate 2>&1 > /dev/null | tee /tmp/config.out | grep error if [ $? -ne 1 ]; then echo "configuration error, exit" echo "$(cat /tmp/config.out)" exit $? fi pid=0 # SIGUSR1-handler siguser1_handler() { echo "stopped" } # SIGTERM-handler sigterm_handler() { if [ $pid -ne 0 ]; then # this will stop the VerneMQ process, but first drain the node from all existing client sessions (-k) if [ -n "$VERNEMQ_KUBERNETES_HOSTNAME" ]; then terminating_node_name=VerneMQ@$VERNEMQ_KUBERNETES_HOSTNAME elif [ -n "$DOCKER_VERNEMQ_SWARM" ]; then terminating_node_name=VerneMQ@$(hostname -i) else terminating_node_name=VerneMQ@$IP_ADDRESS fi /vernemq/bin/vmq-admin cluster leave node=$terminating_node_name -k > /dev/null /vernemq/bin/vmq-admin node stop > /dev/null kill -s TERM ${pid} exit 0 fi } # Setup OS signal handlers trap 'siguser1_handler' SIGUSR1 trap 'sigterm_handler' SIGTERM # Start VerneMQ /vernemq/bin/vernemq console -noshell -noinput $@ & pid=$! wait $pid |
--
Eclipse Mosquitto
Ubuntu 20
1 |
# apt-get install mosquitto mosquitto-clients |
需要重新安裝設定檔可以使用
1 |
# apt-get -o DPkg::options::=--force-confmiss --reinstall install mosquitto |
--
RabbitMQ
MQTT 在 RabbitMQ 只是其中一個 Plugin,不會用
Ubuntu 20
1 |
# apt-get install erlang-base erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssl erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl |
1 |
# apt-get install rabbitmq-server |
1 |
# rabbitmq-plugins enable rabbitmq_mqtt |
--
Mosquitto MySQL plugin 安裝
1 |
# apt-get install libssl-dev mosquitto-dev libmysqlclient-dev |
最後編譯失敗,不會用
--
6,352 total views, 2 views today