聶永的博客

          記錄工作/學(xué)習(xí)的點(diǎn)點(diǎn)滴滴。

          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)

          1. 類(lèi)似于SSH Server,監(jiān)聽(tīng)某個(gè)端口,能夠執(zhí)行傳遞過(guò)來(lái)的命令
          2. 能夠根據(jù)IP地址授權(quán),這樣只有Tsung Master才能夠訪問(wèn)從節(jié)點(diǎn),從節(jié)點(diǎn)之間無(wú)法直接對(duì)連
          3. 需要接受一些操控指令,可以判斷是否存活
          4. 一到兩個(gè)腳本/程序搞定,盡量避免安裝,開(kāi)箱即用
          5. 總之配置、操作一定要簡(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è)

          公告

          所有文章皆為原創(chuàng),若轉(zhuǎn)載請(qǐng)標(biāo)明出處,謝謝~

          新浪微博,歡迎關(guān)注:

          導(dǎo)航

          <2016年7月>
          262728293012
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          統(tǒng)計(jì)

          常用鏈接

          留言簿(58)

          隨筆分類(lèi)(130)

          隨筆檔案(151)

          個(gè)人收藏

          最新隨筆

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 六枝特区| 九龙坡区| 潼南县| 永定县| 芮城县| 波密县| 徐闻县| 伽师县| 江山市| 乐昌市| 连南| 东台市| 沐川县| 师宗县| 白水县| 湟源县| 锡林郭勒盟| 疏附县| 名山县| 班玛县| 罗平县| 丰城市| 砀山县| 阿尔山市| 大城县| 阜新| 菏泽市| 定襄县| 安陆市| 托克托县| 南充市| 泰安市| 尼勒克县| 喀什市| 额济纳旗| 营山县| 武功县| 娄烦县| 铜鼓县| 汝阳县| 上林县|