2024-04-17

Eclipse Mosquitto

Eclipse Mosquitto 是一套開放原始碼的 MQTT Broker。

在 openSUSE 安裝:

sudo zypper in mosquitto

如果要執行的話,使用 systemctl 啟動服務:

sudo systemctl start mosquitto

再來使用 tcl.mqttc 驗證是否可以正確連線。

Subscribe:
package require mqttc

mqttc client "tcp://localhost:1883" "USERSSub" 1 -cleansession 1
client subscribe  "MQTT Examples" 1
while 1 {
    if {[catch {set result [client  receive]}]} {
        puts "Receive error!!!"
        break
    }
    if {[llength $result] > 0} {
        puts "[lindex $result 0] - [lindex $result 1]"
        if {![string compare -nocase [lindex $result 1] "Exit"]} {
            break
        }
    }
}
client unsubscribe  "MQTT Examples"
client close
Publish:
package require mqttc

mqttc client "tcp://localhost:1883" "USERSPub" 1 -timeout 1000
client publishMessage "MQTT Examples" "Hello MQTT!" 1 0
client publishMessage "MQTT Examples" "Exit" 1 0
client close

先執行 Subscribe 的部份,再使用 Publish 發送訊息,確定可以正確執行。


下面是另外一個使用 tcl.mqttc 測試 Subscribe 與 Publish 功能的測試程式:

package require Thread
package require mqttc
catch {console show}

set ::gThread [thread::create {thread::wait} ]
set result 0

proc subscribe { } {
    thread::send -async $::gThread {
        package require mqttc

        mqttc client "tcp://localhost:1883" "USERTest1" 1 -cleansession 1
        client subscribe  "MQTT Examples" 1
        while 1 {
            if {[catch {set result [client  receive]}]} {
                puts "Receive error!!!"
                break
            }
            if {[llength $result] > 0} {
                puts "[lindex $result 0] - [lindex $result 1]"
                if {![string compare -nocase [lindex $result 1] "Exit"]} {
                    break
                }
            }
        }
        client unsubscribe  "MQTT Examples"
        client close
    } ::result
}

subscribe
puts "started test..."

after 250

mqttc client "tcp://localhost:1883" "USERTest2" 1 -timeout 1000
client publishMessage "MQTT Examples" "Hello MQTT!" 1 0
client publishMessage "MQTT Examples" "Exit" 1 0
client close

vwait ::result

2024-04-10

Apache HTTP Server and rivet-fcgi

這是之前在寫 rivet-fcgi 這個幫助我學習 FastCGI 的 prototype 時的筆記,關於 Apache HTTP Server 的,目前我沒有再重新測一次確定完全沒有問題,只是放在這裡先做個記錄。


簡介

Apache HTTP Server 是 Apache 軟體基金會的一個開放原始碼的網頁伺服器軟體,可以在大多數電腦作業系統中運行, 以其高擴充的能力以及眾多的 module 著稱。雖然現在效能被其它的網頁伺服器超過,但是也仍然是一個高效能的伺服器。

在 openSUSE 安裝 Apache2:

sudo zypper install apache2

檢查 Apache 版本:

sudo httpd -v

建立 ssl.conf 設定檔

[req]
prompt = no
default_md = sha256
default_bits = 2048
distinguished_name = dn
x509_extensions = v3_req

[dn]
C = TW
ST = Taiwan
L = Taipei
O = Orange Inc.
OU = IT Department
emailAddress = admin@example.com
CN = localhost

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.localhost
DNS.2 = localhost
IP.1 = 127.0.0.1

透過指令建立開發測試用途的自簽憑證

openssl req -x509 -new -nodes -sha256 -utf8 -days 3650 -newkey rsa:2048 \
-keyout apache.key -out apache.crt -config ssl.conf

將 apache.key 複製到 ssl.key 目錄,apache.crt 複製到 ssl.crt 目錄(需要使用 su 切換到 root 身份或者使用 sudo)。

將 /etc/apache2/vhosts.d/vhost-ssl.template 複製為 vhost-ssl.conf,並修改內容如下:

# Template for a VirtualHost with SSL
# Note: to use the template, rename it to /etc/apache2/vhost.d/yourvhost.conf.
# Files must have the .conf suffix to be loaded.
#
# See /usr/share/doc/packages/apache2/README.QUICKSTART for further hints
# about virtual hosts.
#
# This is the Apache server configuration file providing SSL support.
# It contains the configuration directives to instruct the server how to
# serve pages over an https connection. For detailing information about these
# directives see http://httpd.apache.org/docs/2.4/mod/mod_ssl.html
#
# Do NOT simply read the instructions in here without understanding
# what they do.  They're here only as hints or reminders.  If you are unsure
# consult the online docs. You have been warned.
#

<IfDefine SSL>
<IfDefine !NOSSL>

##
## SSL Virtual Host Context
##

<VirtualHost _default_:443>

    #  General setup for the virtual host
    DocumentRoot "/srv/www/htdocs"
    #ServerName www.example.com:443
    #ServerAdmin webmaster@example.com
    ErrorLog /var/log/apache2/error_log
    TransferLog /var/log/apache2/access_log

    #   SSL Engine Switch:
    #   Enable/Disable SSL for this virtual host.
    SSLEngine on

    #   OCSP Stapling:
    #   Enable/Disable OCSP for this virtual host.
    SSLUseStapling  on

    #   You can use per vhost certificates if SNI is supported.
    SSLCertificateFile /etc/apache2/ssl.crt/apache.crt
    SSLCertificateKeyFile /etc/apache2/ssl.key/apache.key
    #SSLCertificateChainFile /etc/apache2/ssl.crt/vhost-example-chain.crt

    #   Per-Server Logging:
    #   The home of a custom SSL log file. Use this when you want a
    #   compact non-error SSL logfile on a virtual host basis.
    CustomLog /var/log/apache2/ssl_request_log   ssl_combined

    <Directory />
        Options FollowSymLinks
        AllowOverride All
        #    Order deny,allow
        #    Deny from all
    </Directory>

    <Directory /srv/www/htdocs>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
    </Directory>

</VirtualHost>

</IfDefine>
</IfDefine>

主要就是 SSLCertificateFile 與 SSLCertificateKeyFile 這二個項目的設定,端視所放置的位置。


Apache 提供不同的 multiprocessing modules (MPMs) 可以使用,主要有下列的分別:

  • Prefork MPM
  • Worker MPM
  • Event MPM

HTTP/2 支援無法在 Prefork MPM 下執行,所以需要設定使用其它的 MPM,目前建議使用 Event MPM。

Enable http2 mod:

sudo a2enmod http2

Enable HTTP2 flag:

sudo a2enflag HTTP2

Switch from prefork to event:

sudo zypper remove apache2-prefork
sudo zypper install apache2-event

In /etc/sysconfig/apache2 make sure to set

APACHE_MPM="event"

APACHE_START_TIMEOUT="10"

重啟 Apache 2:

sudo systemctl restart apache2

To automatically start the apache server after a reboot:

sudo systemctl enable apache2

Apache 內建支援 CGI,default-server.conf 在目錄內啟用 CGI 與設定 handler 的設定如下:

ScriptAlias /cgi-bin/ "/srv/www/cgi-bin/"

# "/srv/www/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/srv/www/cgi-bin">
    AllowOverride None
    Options +ExecCGI -Includes
    <IfModule !mod_access_compat.c>
        Require all granted
    </IfModule>
    <IfModule mod_access_compat.c>
        Order allow,deny
        Allow from all
    </IfModule>
</Directory>

Options +ExecCGI 就是允許執行 CGI 的設定。


檢查目前載入的模組:

sudo apache2ctl -M

FastCGI

Apache mod_fcgid 是 Apache Http Server 用來支援 FastCGI 協定的模組。 FastCGI 是另外一種克服 CGI 缺點的發展路線,也就是將網頁伺服器與應用程式伺服器分開的方式, 而程式會持續執行,這樣就不需要每一個請求都需要產生一個子行程來運行。

下面是在 openSUSE 安裝的方式:

sudo zypper install apache2-mod_fcgid

接下來設定 Apache Http Server 的部份。
首先允許必要的模式:

sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo a2enmod fcgid

下面使用的方式配合 spawn-fcgi
我們需要撰寫 spawn-fcgi 的 systemd service,在 /usr/lib/systemd/system 目錄下建立 spawnfcgi.service,內容如下:

[Unit]
Description=Spawn FCGI service
After=nss-user-lookup.target

[Service]
Type=forking
Environment=WORKERS=1
ExecStart=/usr/bin/spawn-fcgi \
    -F ${WORKERS} \
    -u wwwrun \
    -g www \
    -s /var/run/%p.sock \
    -P /var/run/%p.pid \
    -- /usr/bin/rivet-fcgi
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

(其中 -u 指定 user,-g 指定 group,隨著平台的不同可能有不同的設定。
rivet-fcgi 是我自己撰寫的工具。)

下面是測試我自己寫的工具的設定。
修改 /etc/apache2/conf.d 目錄下的檔案 mod_fcgid.conf,內容如下:

##
#<FilesMatch "\.php$">
#    AddHandler fcgid-script .php
#    Options +ExecCGI
#    FcgidWrapper /srv/www/cgi-bin/php5 .php
#</FilesMatch>
##
DirectoryIndex index.rvt index.tcl
<FilesMatch "\.(rvt|tcl)$">
    SetHandler "proxy:unix:/var/run/spawnfcgi.sock|fcgi://localhost/"
    #CGIPassAuth on
</FilesMatch>

而後啟動(或重新啟動)spawn-fcgi 與 apache2 的服務,接著進行測試是否有正確設定。
(注意:PHP-FPM 也可以使用類似的設定手法,只是 spawn-fcgi 設定的部份變成為設定 php-fpm 的參數, 而 web server 這邊的副檔名參數與連線參數需要修改。)

參考資料

tcl-opencv v0.17

tcl-opencv

 

已經更新版本為 v0.17 一段時間,只是現在才發佈在這個部落格上。 主要是增加 BarcodeDetector 的支援,以及修正 test cases 的錯誤。

  • Implement command: BarcodeDetector
  • Implement command: stackBlur
  • Implement command: hasNonZero
  • Add ::cv::REDUCE_SUM2 option to ::cv::reduce