tsung笔记之分布式增强跳出ssh羁绊篇 -凯发k8网页登录

记录工作/学习的点点滴滴。

tsung笔记之分布式增强跳出ssh羁绊篇

前言

erlang天生支持分布式环境,tsung框架的分布式压测受益于此,简单轻松操控子节点生死存亡、派发任务等不费吹灰之力。

tsung启动分布式压测时,主节点tsung_controller默认情况下需要通过ssh通道连接到远程机器上启动从节点,那么问题便来了,一般互联网公司基于跳板/堡垒机/网关授权方式访问机房服务器,那么ssh机制失效,并且被明令禁止。ssh不通,tsung主机启动不了从机,分布式更无从谈起。

那么如何解决这个问题呢,让tsung在复杂的机房网络环境设定下更加如鱼得水,将是本文所讨论的内容。


rsh:remote shell

rsh,remote shell缩写,维基百科上英文解释:。作为一个终端工具,linux界鸟哥曾经写过 。

在centos下安装也简单:

yum install rsh

erlang借助于rsh命令行工具通过ssh通道连接到从节点启动tsung应用,下面可以看到rsh工具本身失去了原本的含义,类似于exec命令功效。

比如erlang主节点(假设这个服务器名称为node_master,并且已经在/etc/hosts文件建立了ip地址映射)在启动时指定rsh的可选方式为ssh:

erl -rsh ssh -sname foo -setcookie mycookie

启动之后,要启动远程主机节点名称为node_slave的子节点:

slave:start(node_slave, bar, "-setcookie mycookie").

上面erlang启动从节点函数,最终被翻译为可执行的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的启动命令,要求主机node_slave自身也要安装了erlang的运行时环境才行。

从节点的启动命令最终依赖于ssh连接并远程执行,其通用一般格式为:

ssh hostname/ip command

这就是基于erlang构建的tsung操控从节点启动的最终实现机制。

其它语言中,master启动slave也是如此机制

ssh为通用方案,但不是最好的方案

业界选用机制连接远程unix/linux服务器主机,分布式环境下要能够自由免除密码方式启动远程主机上(这里指的是内部lan环境)应用,一般需要设置公钥,需要传递公钥,需要保存到各自机器上,还有经常遇到权限问题,很是麻烦,这是其一。若要取消某台服务器登陆授权,则需要被动修改公钥,也是不够灵活。

另外一般互联网公司处于安全考虑都会禁止公司内部人员直接通过ssh方式登录到远程主机进行操作,这样导致ssh通道失效,tsung主机通过ssh连接到从机并执行命令,也就不可能了。

其实,在基于分布式压测环境下,快速租赁、快速借用/归还的模型就很适合。一般公司很少会存在专门用于压测的大量空闲机器,但是线上会运行着当前负载不高的服务器,可以拿来用作压测客户端使用,用完就归还。因为压测不会是长时间运行的服务,其为短时间行为。这种模式下就不适合复杂的ssh公钥满天飞,后期忘记删除的情况,在压测端超多的情况下,无疑也将造成运维成本激增,安全性降低等问题。

ssh替换方案:一种快速租赁模式远程终端方案

现在需要寻找一种新的代替方案,一种适应快速租赁的远程终端实现机制。

替换方案要求点

  1. 类似于ssh server,监听某个端口,能够执行传递过来的命令
  2. 能够根据ip地址授权,这样只有tsung master才能够访问从节点,从节点之间无法直接对连
  3. 需要接受一些操控指令,可以判断是否存活
  4. 一到两个脚本/程序搞定,尽量避免安装,开箱即用
  5. 总之配置、操作一定要简单,实际运维成本一定要低

没找到很轻量的实现,可以设计并实现这样一种方案。

服务器端守护进程

轻量级服务端守护进程 = 一个监控端口的进程(rsh_daemon.sh) 执行命令过滤功能(rsh_filter)

rsh_daemon.sh 负责守护进程的管理:

  • 基于centos 6/7默认安装的ncat程序
  • 主要用于管理19999端口监听
  • start/stop/restart 负责监控进程启动、关闭
  • status 查看进程状态
  • kill 提供手动方式关闭并删除掉自身
  • rsh_filter用于检测远程传入命令并进行处理
    • 接收ping指令,返回pong
    • 执行erlang从节点命令,并返回 done 字符串
    • 对不合法命令,直接关闭

rsh_daemon.sh代码很简单:

#!/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  start|stop|status|restart"
    echo "options:"
    echo "    -a   allow only given hosts to connect to the server (default is tsung_controller)"
    echo "    -p          use the special port for listen (default is 19999)"
    echo "    -s  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

总结一下:

  • 基于ncat监听19999端口提供bind shell机制,但限制有限ip可访问
  • 动态生成命令过滤脚本rsh_filter.sh,执行erlang从节点命令

请参考:

客户端连接方案

服务器端已经提供了端口接入并准备好了接收指令,客户端(rsh_client.sh)可以进行连接和交互了:

  • 类似ssh客户端接收方式:rsh_client.sh host/ip command
  • 完全基于nc命令,连接远程主机
  • 连接成功,发送命令
  • 得到相应,流程完成

一样非常少的代码呈现。

#!/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主节点如何启动

有了ssh替换方案,那主节点就可以这样启动了:

erl -rsh ~/.tsung/rsh_client.sh -sname foo -setcookie mycookie

比如当tsung需要连接到另外一台服务器上启动从节点时,它最终会翻译成下面命令:

/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

客户端脚本rsh_client.sh则最终需要执行连接到服务器、并发送命的命令:

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

这样就实现了和ssh一样的功能了,很简单吧。

tsung如何切换切换?

为tsung启动添加-r参数指定即可:

tsung -r ~/.tsung/rsh_client.sh -f tsung.xml start

进阶:可指定运行命令路径

rsh_client.sh脚本最后一行修改一下,指定目标服务器erl运行命令:

#!/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

上面脚本所依赖的上下文环境可以是这样的,机房服务器操作系统和版本一致,我们把erlang 18.1整个运行时环境在一台机器上已经安装的目录(比如目录名为otp_18),拷贝到远程主机/root/.tsung/目录,相比于安装而言,可以让tsung运行依赖的eralng环境完全可以移植化(portable),一次安装,多次复制。

代码托管地址

本文所谈及代码,都已经托管在github:

后续代码更新、bug修复等,请直接参考该仓库。

小结

简单一套新的替换ssh通道无密钥登陆远程主机c/s模型,虽然完整性上无法与ssh相比,但胜在简单够用,完全满足了当前业务需要,并且其运维成本低,无疑让tsung在复杂服务器内网环境下适应性又朝前多走了半里路。

下一篇将介绍为tsung增加ip直连特性支持,使其分布式网络环境下适应性更广泛一些。

posted on 2016-07-27 09:28 nieyong 阅读(3220) 评论(0)  编辑  收藏 所属分类: 压测

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

2016年7月
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

统计

常用链接

留言簿(58)

随笔分类(129)

随笔档案(149)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜

网站地图