Tsung筆記之分布式增強(qiáng)跳出SSH羈絆篇
前言
Erlang天生支持分布式環(huán)境,Tsung框架的分布式壓測(cè)受益于此,簡(jiǎn)單輕松操控子節(jié)點(diǎn)生死存亡、派發(fā)任務(wù)等不費(fèi)吹灰之力。
Tsung啟動(dòng)分布式壓測(cè)時(shí),主節(jié)點(diǎn)tsung_controller默認(rèn)情況下需要通過(guò)SSH通道連接到遠(yuǎn)程機(jī)器上啟動(dòng)從節(jié)點(diǎn),那么問(wèn)題便來(lái)了,一般互聯(lián)網(wǎng)公司基于跳板/堡壘機(jī)/網(wǎng)關(guān)授權(quán)方式訪問(wèn)機(jī)房服務(wù)器,那么SSH機(jī)制失效,并且被明令禁止。SSH不通,Tsung主機(jī)啟動(dòng)不了從機(jī),分布式更無(wú)從談起。
那么如何解決這個(gè)問(wèn)題呢,讓tsung在復(fù)雜的機(jī)房網(wǎng)絡(luò)環(huán)境設(shè)定下更加如魚(yú)得水,將是本文所討論的內(nèi)容。?
RSH:Remote Shell
RSH,remote shell縮寫(xiě),維基百科上英文解釋?zhuān)?a >https://en.wikipedia.org/wiki/Remote_Shell。作為一個(gè)終端工具,Linux界鳥(niǎo)哥曾經(jīng)寫(xiě)過(guò) RSH客戶(hù)端和服務(wù)器端搭建教程。
在CentOS下安裝也簡(jiǎn)單:
yum install rsh
Erlang借助于rsh命令行工具通過(guò)SSH通道連接到從節(jié)點(diǎn)啟動(dòng)Tsung應(yīng)用,下面可以看到rsh工具本身失去了原本的含義,類(lèi)似于exec
命令功效。
比如Erlang主節(jié)點(diǎn)(假設(shè)這個(gè)服務(wù)器名稱(chēng)為node_master
,并且已經(jīng)在/etc/hosts文件建立了IP地址映射)在啟動(dòng)時(shí)指定rsh的可選方式為SSH:
erl -rsh ssh -sname foo -setcookie mycookie
啟動(dòng)之后,要啟動(dòng)遠(yuǎn)程主機(jī)節(jié)點(diǎn)名稱(chēng)為node_slave
的子節(jié)點(diǎn):
slave:start(node_slave, bar, "-setcookie mycookie").
上面Erlang啟動(dòng)從節(jié)點(diǎn)函數(shù),最終被翻譯為可執(zhí)行的shell命令:
ssh node_slave erl -detached -noinput -master foo@node_master -sname bar@node_slave -s slave slave_start foo@node_master slave_waiter_0 -setcookie mycookie
erl
命令Erlang的啟動(dòng)命令,要求主機(jī)node_slave
自身也要安裝了Erlang的運(yùn)行時(shí)環(huán)境才行。
從節(jié)點(diǎn)的啟動(dòng)命令最終依賴(lài)于SSH連接并遠(yuǎn)程執(zhí)行,其通用一般格式為:
ssh HOSTNAME/IP Command
這就是基于Erlang構(gòu)建的Tsung操控從節(jié)點(diǎn)啟動(dòng)的最終實(shí)現(xiàn)機(jī)制。
其它語(yǔ)言中,Master啟動(dòng)Slave也是如此機(jī)制
SSH為通用方案,但不是最好的方案
業(yè)界選用SSH機(jī)制連接遠(yuǎn)程Unix/Linux服務(wù)器主機(jī),分布式環(huán)境下要能夠自由免除密碼方式啟動(dòng)遠(yuǎn)程主機(jī)上(這里指的是內(nèi)部Lan環(huán)境)應(yīng)用,一般需要設(shè)置公鑰,需要傳遞公鑰,需要保存到各自機(jī)器上,還有經(jīng)常遇到權(quán)限問(wèn)題,很是麻煩,這是其一。若要取消某臺(tái)服務(wù)器登陸授權(quán),則需要被動(dòng)修改公鑰,也是不夠靈活。
另外一般互聯(lián)網(wǎng)公司處于安全考慮都會(huì)禁止公司內(nèi)部人員直接通過(guò)SSH方式登錄到遠(yuǎn)程主機(jī)進(jìn)行操作,這樣導(dǎo)致SSH通道失效,Tsung主機(jī)通過(guò)SSH連接到從機(jī)并執(zhí)行命令,也就不可能了。
其實(shí),在基于分布式壓測(cè)環(huán)境下,快速租賃、快速借用/歸還的模型就很適合。一般公司很少會(huì)存在專(zhuān)門(mén)用于壓測(cè)的大量空閑機(jī)器,但是線上會(huì)運(yùn)行著當(dāng)前負(fù)載不高的服務(wù)器,可以拿來(lái)用作壓測(cè)客戶(hù)端使用,用完就歸還。因?yàn)閴簻y(cè)不會(huì)是長(zhǎng)時(shí)間運(yùn)行的服務(wù),其為短時(shí)間行為。這種模式下就不適合復(fù)雜的SSH公鑰滿天飛,后期忘記刪除的情況,在壓測(cè)端超多的情況下,無(wú)疑也將造成運(yùn)維成本激增,安全性降低等問(wèn)題。
SSH替換方案:一種快速租賃模式遠(yuǎn)程終端方案
現(xiàn)在需要尋找一種新的代替方案,一種適應(yīng)快速租賃的遠(yuǎn)程終端實(shí)現(xiàn)機(jī)制。
替換方案要求點(diǎn)
- 類(lèi)似于SSH Server,監(jiān)聽(tīng)某個(gè)端口,能夠執(zhí)行傳遞過(guò)來(lái)的命令
- 能夠根據(jù)IP地址授權(quán),這樣只有Tsung Master才能夠訪問(wèn)從節(jié)點(diǎn),從節(jié)點(diǎn)之間無(wú)法直接對(duì)連
- 需要接受一些操控指令,可以判斷是否存活
- 一到兩個(gè)腳本/程序搞定,盡量避免安裝,開(kāi)箱即用
- 總之配置、操作一定要簡(jiǎn)單,實(shí)際運(yùn)維成本一定要低
沒(méi)找到很輕量的實(shí)現(xiàn),可以設(shè)計(jì)并實(shí)現(xiàn)這樣一種方案。
服務(wù)器端守護(hù)進(jìn)程
輕量級(jí)服務(wù)端守護(hù)進(jìn)程 = 一個(gè)監(jiān)控端口的進(jìn)程(rsh_daemon.sh
) + 執(zhí)行命令過(guò)濾功能(rsh_filter)
rsh_daemon.sh
負(fù)責(zé)守護(hù)進(jìn)程的管理:
- 基于CentOS 6/7默認(rèn)安裝的
ncat
程序 - 主要用于管理19999端口監(jiān)聽(tīng)
- start/stop/restart 負(fù)責(zé)監(jiān)控進(jìn)程啟動(dòng)、關(guān)閉
- status 查看進(jìn)程狀態(tài)
- kill 提供手動(dòng)方式關(guān)閉并刪除掉自身
rsh_filter
用于檢測(cè)遠(yuǎn)程傳入命令并進(jìn)行處理- 接收ping指令,返回pong
- 執(zhí)行Erlang從節(jié)點(diǎn)命令,并返回 done 字符串
- 對(duì)不合法命令,直接關(guān)閉
rsh_daemon.sh
代碼很簡(jiǎn)單:
#!/bin/bash
# the script using for start/stop remote shell daemon server to replace the ssh server
PORT=19999
FILTER=~/tmp/_tmp_rsh_filter.sh
# the tsung master's hostname or ip
tsung_controller=tsung_controller
SPECIAL_PATH=""
PROG=`basename $0`
prepare() {
cat << EOF > $FILTER
#!/bin/bash
ERL_PREFIX="erl"
while true
do
read CMD
case \$CMD in
ping)
echo "pong"
exit 0
;;
*)
if [[ \$CMD == *"\${ERL_PREFIX}"* ]]; then
exec $SPECIAL_PATH\${CMD}
fi
exit 0
;;
esac
done
EOF
chmod a+x $FILTER
}
start() {
NUM=$(ps -ef|grep ncat | grep ${PORT} | grep -v grep | wc -l)
if [ $NUM -gt 0 ];then
echo "$PROG already running ..."
exit 1
fi
if [ -x "$(command -v ncat)" ]; then
echo "$PROG starting now ..."
ncat -4 -k -l $PORT -e $FILTER --allow $tsung_controller &
else
echo "no exists ncat command, please install it ..."
fi
}
stop() {
NUM=$(ps -ef|grep ncat | grep rsh | grep -v grep | wc -l)
if [ $NUM -eq 0 ]; then
echo "$PROG had already stoped ..."
else
echo "$PROG is stopping now ..."
ps -ef|grep ncat | grep rsh | grep -v grep | awk '{print $2}' | xargs kill
fi
}
status() {
NUM=$(ps -ef|grep ncat | grep rsh | grep -v grep | wc -l)
if [ $NUM -eq 0 ]; then
echo "$PROG had already stoped ..."
else
echo "$PROG is running ..."
fi
}
usage() {
echo "Usage: $PROG <options> start|stop|status|restart"
echo "Options:"
echo " -a <hostname/ip> allow only given hosts to connect to the server (default is tsung_controller)"
echo " -p <port> use the special port for listen (default is 19999)"
echo " -s <the_erl_path> use the special erlang's erts bin path for running erlang (default is blank)"
echo " -h display this help and exit"
exit
}
while getopts "a:p:s:h" Option
do
case $Option in
a) tsung_controller=$OPTARG;;
p) PORT=$OPTARG;;
s) TMP_ERL=$OPTARG
if [ "$OPTARG" != "" ]; then
if [[ "$OPTARG" == *"/" ]]; then
SPECIAL_PATH=$OPTARG
else
SPECIAL_PATH=$OPTARG"/"
fi
fi
;;
h) usage;;
*) usage;;
esac
done
shift $(($OPTIND - 1))
case $1 in
start)
prepare
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
usage
;;
esac
總結(jié)一下:
- 基于
ncat
監(jiān)聽(tīng)19999端口提供bind shell機(jī)制,但限制有限IP可訪問(wèn) - 動(dòng)態(tài)生成命令過(guò)濾腳本
rsh_filter.sh
,執(zhí)行Erlang從節(jié)點(diǎn)命令
請(qǐng)參考:https://github.com/weibomobile/tsung_rsh/blob/master/rsh_daemon.sh
客戶(hù)端連接方案
服務(wù)器端已經(jīng)提供了端口接入并準(zhǔn)備好了接收指令,客戶(hù)端(rsh_client.sh
)可以進(jìn)行連接和交互了:
- 類(lèi)似SSH客戶(hù)端接收方式:
rsh_client.sh Host/IP Command
- 完全基于
nc
命令,連接遠(yuǎn)程主機(jī) - 連接成功,發(fā)送命令
- 得到相應(yīng),流程完成
一樣非常少的代碼呈現(xiàn)。
#!/bin/sh
PORT=19999
if [ $# -lt 2 ]; then
echo "Invalid number of parameters"
exit 1
fi
REMOTEHOST="$1"
COMMAND="$2"
if [ "${COMMAND}" != "erl" ]; then
echo "Invalid command ${COMMAND}"
exit 1
fi
shift 2
echo "${COMMAND} $*" | /usr/bin/nc ${REMOTEHOST} ${PORT}
Erlang主節(jié)點(diǎn)如何啟動(dòng)
有了SSH替換方案,那主節(jié)點(diǎn)就可以這樣啟動(dòng)了:
erl -rsh ~/.tsung/rsh_client.sh -sname foo -setcookie mycookie
比如當(dāng)Tsung需要連接到另外一臺(tái)服務(wù)器上啟動(dòng)從節(jié)點(diǎn)時(shí),它最終會(huì)翻譯成下面命令:
/bin/sh /root/.tsung/rsh_client.sh node_slave erl -detached -noinput -master foo@node_master -sname bar@node_slave -s slave slave_start foo@node_master slave_waiter_0 -setcookie mycookie
客戶(hù)端腳本rsh_client.sh
則最終需要執(zhí)行連接到服務(wù)器、并發(fā)送命的命令:
echo "erl -detached -noinput -master foo@node_master -sname bar@node_slave -s slave slave_start foo@node_master slave_waiter_0 -setcookie mycookie" | /usr/bin/nc node_slave 19999
這樣就實(shí)現(xiàn)了和SSH一樣的功能了,很簡(jiǎn)單吧。
Tsung如何切換切換?
為tsung啟動(dòng)添加-r
參數(shù)指定即可:
tsung -r ~/.tsung/rsh_client.sh -f tsung.xml start
進(jìn)階:可指定運(yùn)行命令路徑
rsh_client.sh
腳本最后一行修改一下,指定目標(biāo)服務(wù)器erl運(yùn)行命令:
#!/bin/sh
PORT=19999
if [ $# -lt 2 ]; then
echo "Invalid number of parameters"
exit 1
fi
REMOTEHOST="$1"
COMMAND="$2"
if [ "${COMMAND}" != "erl" ]; then
echo "Invalid command ${COMMAND}"
exit 1
fi
shift 2
exec echo "/root/.tsung/otp_18/bin/erl $*" | /usr/bin/nc ${REMOTEHOST} 19999
上面腳本所依賴(lài)的上下文環(huán)境可以是這樣的,機(jī)房服務(wù)器操作系統(tǒng)和版本一致,我們把Erlang 18.1整個(gè)運(yùn)行時(shí)環(huán)境在一臺(tái)機(jī)器上已經(jīng)安裝的目錄(比如目錄名為otp_18),拷貝到遠(yuǎn)程主機(jī)/root/.tsung/
目錄,相比于安裝而言,可以讓Tsung運(yùn)行依賴(lài)的Eralng環(huán)境完全可以移植化(Portable),一次安裝,多次復(fù)制。
代碼托管地址
本文所談及代碼,都已經(jīng)托管在github:
https://github.com/weibomobile/tsung_rsh
后續(xù)代碼更新、BUG修復(fù)等,請(qǐng)直接參考該倉(cāng)庫(kù)。
小結(jié)
簡(jiǎn)單一套新的替換SSH通道無(wú)密鑰登陸遠(yuǎn)程主機(jī)C/S模型,雖然完整性上無(wú)法與SSH相比,但勝在簡(jiǎn)單夠用,完全滿足了當(dāng)前業(yè)務(wù)需要,并且其運(yùn)維成本低,無(wú)疑讓Tsung在復(fù)雜服務(wù)器內(nèi)網(wǎng)環(huán)境下適應(yīng)性又朝前多走了半里路。
下一篇將介紹為T(mén)sung增加IP直連特性支持,使其分布式網(wǎng)絡(luò)環(huán)境下適應(yīng)性更廣泛一些。
posted on 2016-07-27 09:28 nieyong 閱讀(3340) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): 壓測(cè)