[Ubuntu 15.04 | Raspberry Pi 2]_MQTT 安裝、設定、Connection limit 1024解決、模擬程式 快速筆記文

MQTT是一個輕量型的溝通的協定,詳細的介紹我就不贅述了(想偷懶…)

0912embmqtt01

(圖片來自https://tessel.io/blog/98339010407/mqtt-on-tessel)

 

因為這篇也是快速筆記文,就不做這麼多技術介紹說明,

請直接參考:http://cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pimqtt-android.html

比較詳盡啦~

 

我這邊筆記安裝、還有設定部分的簡介,起個頭。

還有寫一些我在大規模連線測試會遇到的CONNECTION錯誤解決方式


 

I.安裝

這裡走Debian體系,所以RPI跟Ubuntu都可以

RPI 2我用Rasbian, PC用Ubuntu 15.04 x64

 

安裝有兩種方式,一種是抓SOURCE CODE回來COMPILE,可以調整的設定較多,例如開啟關閉TLS/SSL等特殊的功能

可以參考對岸同胞的文章:http://blog.csdn.net/shagoo/article/details/7910598

 

但上面的連結還有介紹mosquitto.conf的設定,所以用下面第二種apt的裝法,一樣可以參考

 

第二種是apt-get,就比較簡單了

wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key

sudo apt-key add mosquitto-repo.gpg.key

rm mosquitto-repo.gpg.key

cd /etc/apt/sources.list.d/

sudo wget http://repo.mosquitto.org/debian/mosquitto-repo.list

sudo apt-get update

sudo apt-get install mosquitto mosquitto-clients

 

安裝好之後,其實就會隨著開機啟動MQTT把這台機器也當作Topic Server,可以做本地端測試

 

開啟兩個終端機,分別執行下面的1以及2

  1. 建立Subscriber(訂閱者),訂閱topic名稱為NTEX_IOT_TOPIC01
mosquitto_sub -d -t NTEX_IOT_TOPIC01

 

2.建立Publisher(發布者),發佈到topic名稱為NTEX_IOT_TOPIC01

mosquitto_pub -d -t NTEX_IOT_TOPIC01 -m "Test message. Test message. Test message."

 

 

此時在1號終端機,Subscriber應該會看到來自Publisher的訊息

 

而2號終端機所key的那行指令,若預設沒有加上-h指定topic server,則會以自身當作topic server以及一個publisher的腳色

 

另外在Mosquitt的設定,位於/etc/mosquitto/conf.d底下,需要注意的是/etc/mosquitto/mosquitto.conf有指出請把自定義的設定檔放到conf.d資料夾底下

但我這邊用apt-get安裝的mosquitto,conf.d底下只有README,可以透過在/usr/share/doc/mosquitto/examples/mosquitto.conf.gz解壓縮出來的mosquitto.conf

 

貼到/etc/mosquitto/conf.d/底下,並且可以進行其設定,預設是不需要調整甚麼啦…

但我在之後有遇到連線數不能超過1024的問題,才來檢查這,但問題不是這邊,因為預設如果沒有這個設定檔,連線數量是無上限的,

不過還是筆記一下,限制連線數的屬性名稱為max_connections,其實這邊就算修改為無上限,但還是會受限於系統的限制,不過我這邊為了測試用

還是手動反註解他,讓max_connections = -1,也就是無限制的意思,後文會回來提這個部分。

 

設定檔詳細可以參考前文所貼的http://blog.csdn.net/shagoo/article/details/7910598

以及官方說明文件:http://mosquitto.org/man/mosquitto-conf-5.html

 


 

II. Python端

這邊也提供一簡單的Python Subscriber程式範例:

import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))

    client.subscribe("IOT_NEAT_TOPIC01")

def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("mqtt.phodal.com", 1883, 60)
client.loop_forever()

 

比較特別的是client.connect,第一欄位填Topic Server位置,第二欄位是Topic Server port,最後是Client timeout時間(秒)

 

預設用mqtt官方測試伺服器即可驗證這個腳本是否可以work,可以之後再替換成自己的Topic Server即可。

 

另外需要安裝pah.mqtt.client的lib,可以用pip安裝

pip install paho-mqtt

 

而在Publisher端的Python:

import paho.mqtt.client as mqtt

_g_cst_ToMQTTTopicServerIP = "塞你的Topic Server IP"
_g_cst_ToMQTTTopicServerPort = 1883 #預設port
_g_cst_MQTTTopicName = "IOT_NEAT_TOPIC01" #TOPIC名稱

def MQTT_TEST():
    print ">>MQTT Publishing test<<"
    mqttc = mqtt.Client("python_pub")
    mqttc.connect(_g_cst_ToMQTTTopicServerIP, _g_cst_ToMQTTTopicServerPort)
    mqttc.publish(_g_cst_MQTTTopicName, "HI")
    mqttc.loop(2)  #timeout 2sec

MQTT_TEST()

 

 

ref:

http://www.phodal.com/blog/python-paho-mqtt-mosquitto/

http://mosquitto.org/documentation/python/

https://pypi.python.org/pypi/paho-mqtt

https://sakshambhatla.wordpress.com/2014/08/11/simple-mqtt-broker-and-client-in-python/

 


III. 解決Topic Server有超過1024筆連線,Server端出現Error: The connection was lost.的問題

其實這個問題是由作業系統本身限制而非Mosquitto所限制的,

因是bash有限制裡面執行程式的open file數量(for socket)以及user processes.
可以再當前的terminal打ulimit -nu 65535,在手動執行mosquitto,就可以解決這個問題
若要手動執行mosquitto,需要pkill背景已經透過init執行的mosquitto,接著再去重新手動執行起mosquitto:
sudo /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

 

一勞永逸的方式,是設定/etc/init.d/mosquitto 把ulimit -n加大,在init啟動mosquito時就會特別把他的執行環境enlarge
在start)後面加入ulimit -n 65535 (可以更大,看你需要到多少…)
case "$1" in
  start)
        ulimit -n 65535
        if init_is_upstart; then
            exit 1

 

另外,若增大每個user開的terminal ulimit可以把ulimit寫在/etc/profile最後一行,跟本文主題無關XD
若ulimit -a看到沒有增加,可以寫在/etc/security/limits.conf
* - nofile 1048576
root - nofile 1048576
 最大值依照系統而變,16.04是1048576
參考:http://www.jianshu.com/p/23ee9db2a620、http://blogger.liaohaha.tw/2012/04/etcsecuritylimitsconf.html、http://serverfault.com/questions/292237/apply-ulimit-globally-on-ubuntu

 

IV. 模擬Subscriber

下面的腳本可以測出大概一個topic server可以乘載到什麼數量的subscriber,但只有簡單的線性for迴圈,並沒有平行化運作,所以僅限測連線所耗費的資源跟部分模擬連線數量限制所用

#!/bin/bash
c=1

while [ $c -le 28000 ]
do
mosquitto_sub -h 192.168.1.51 -d -t IOT_NEAT_TOPIC01 -k 900 &
(( c++ ))
echo $c

#sleep 0.001
done

-k 900為這個subscriber每900秒會發出keepalive保持這個subscriber持續連著

 

上面會產生28000個subscriber,這個數字是因為我在Ubuntu 14.04 LTS的VM上,運行的極限是28235個,再繼續的話,subscriber simulator端出現:cannot assign requested address

原因來自短時間CONNECTION太多了,模擬的時候超過2萬~3萬時會出現,是單一subscriber simulator運行的系統port都被佔用了
建議單一系統上subscriber simulator模擬不要超過25k台。
但可以分別run在其他的系統上,來測出topic server的極限。
而執行完subscriber simulator後,可以用netstat來查看client端到底生了多少個subscriber出來
netstat -an | grep :80 | wc -l

 

最後po一下一個subscriber simulator模擬28000個subscriber的資源消耗量

2015-05-24_23-10-13

另外上面這張圖其實有分開跑在不同的兩台vm中(因為作業系統最大client連線port不夠),所以下圖是topic server,CPU才有換Thread在loading。

也可以發現Server端的RAM消耗其實沒有很大,頂多56K的連線數量大概只有吃掉200M左右的RAM,以及不知道是不是因為subscriber沒有同時發起連線到Topic Server的緣故,

Topic Server只有看到單一Thread有loading。

2015-05-24_23-10-30

 

 

以上~

 

 

1 Comment

  1. 感謝,獲益良多,連線數是個問題,因為keepalive似乎會占用socket導致新的連線failed

Leave a comment

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料