一種搭建分布式測試環境和批量性能測試的思路
在搜索引擎的測試過程中,經常會遇到以下兩個問題:
● 需要搭建和更新分布式測試環境
● 在性能測試時,我們需要測試不同集群規模和配置下的環境時,如何自動更新測試環境和批量進行性能測試
因此,我們需要設計一個腳本,這個腳本可以幫我來完成這些事。
在這里,我推薦使用Python,理由有:
● 寫起來比較快(測試時間本來就比較緊張),不可能用C或者Java了
● 語法比較清晰,Shell、Perl這些維護起來太亂
● 自帶的庫、第三方的庫比較豐富
● 另外,我個人比較喜歡Python的mako模版引擎和paramikossh2庫。
其實不用paramiko也可以,只要把機器ssh打通就可以。但我個人不太喜歡這種方式,覺得耦合性太強(只能在Linux下運行了)。
設計
批量性能測試的設計
我很喜歡采用YAML格式,YAML格式的一大好處就是可以很方便的定義List、Map等類型
|
在阿里的搜索平臺這邊,我們大多使用abench作為性能測試工具,它是一個命令行工具,只要命令+參數就可以了,比起JMeter要寫JMeter腳本簡單。因此,我再在配置文件中設計一下abench的命令格式。
因為在運行命令中,有很多參數需要替換成上述測試用例設定的參數,因此需要采用模版引擎的方式。Python的模版引擎很多,我個人比較推薦mako。
|
|
自動更新測試環境
在我實際測試過程中,因為要更新的環境其實相當復雜,最多的時侯需要去10幾臺機器上做更新環境、停止/啟動進程的操作。但我這里主要介紹思路,多一些機器和進程其實都一樣。
接著剛才的配置文件,我們只是在每一個task中設計了加壓任務,但在加壓前需要更新哪些環境沒有涉及,按照阿里巴巴的ISearch架構,我 就啟動一個一行兩列的Searcher環境,2列Searcher上有一個Merger,然后再有一個clustermap來監控。
- abenchPath: /opt/usr/bin/abench # abench在哪兒?
- abenchCommand: "${abenchPath} -p ${parallelNum} -s ${seconds} -k --http -o /dev/null ${targetHost} ${targetPort} ${queryFilePath}"
- # 關于Searcher的一些通用配置
- searcher:
- templateConfigFile: /home/admin/access-log/searcher_server.cfg # 因為啟動時的監聽端口等信息需要從下面的運行任務中讀取,因此這個也設計成一個模版文件
- templateLogConfigFile: /home/admin/access-log/searcher_log.cfg
- # 在Search機器上操作的命令
- commands:
- - "${searchRoot}/bin/is_searcher_server -c ${configFile} -l ${logConfigFile} -k stop > /dev/null 2>&1"
- - "${searchRoot}/bin/is_searcher_server -c ${configFile} -l ${logConfigFile} -k start -d > /dev/null 2>&1"
- # 關于Merger的一些通用配置,和Searcher差不多,就不寫了
-
- tasks:
- # 第一個測試用例,我可能需要測試單線程的情況
- -
- id: 1 # ID的作用是你在腳本中可以拿id作為結果存放的目錄
- parallelNum: 1 # 并發數
- seconds: 1800 # 壓半個小時
- targetHost: 10.20.137.22 # 目標主機
- targetPort: 9999
- queryFilePath: /home/admin/access-log/add-600w.query # 請求放在這兒
-
- # 兩臺Search機器,定義一個List
- searchers:
- -
- host: 10.20.150.61
- port: 6322 # 監聽的端口
- username: test # 因為需要通過ssh協議登錄上去操作,因此需要用戶名密碼。如果你已經把機器ssh都打通了,那就不需要了
- password: 12345
- configFile: "${searchRoot}/scripts/conf/searcher_server.cfg" # 啟動時運行的配置文件
- logConfigFile: "${searchRoot}/scripts/conf/searcher_log.cfg" # 啟動時運行的日志文件
- -
- host: 10.20.150.60
- port: 6322
- username: test
- password: 12345
- configFile: "${searchRoot}/scripts/conf/searcher_server.cfg"
- logConfigFile: "${searchRoot}/scripts/conf/searcher_log.cfg"
-
- # 我這邊只有一臺merger,如果merger也是有多臺的話,也可以把這個設計成一個List
- merger:
- host: 10.20.137.22
- port: 6088
- username: test
- password: 12345
- configFile: "${searchRoot}/scripts/conf/merger_server.cfg"
|
上述就是關于searcher和merger多行多列的配置,下面我們完善一下我們剛才的Python腳本
- # 得的一個ssh登錄后的client對象,用于調用遠程機器上的命令
- def getClient(host, port, username, password):
- client = paramiko.SSHClient()
- client.load_system_host_keys()
- client.set_missing_host_key_policy(paramiko.WarningPolicy()
- client.connect(hostname, port, username, password)
- return client
-
- # 得到一個sftp對象,因為需要scp渲染好的配置文件什么的,因此需要sftp對象,它的put方法其實就類似scp
- def getSftp(host, port, username, password):
- transport = paramiko.Transport((hostname, port))
- transport.connect(username=username, password=password)
- sftp = paramiko.SFTPClient.from_transport(transport)
- return sftp
-
- # 更新和部署Searchers
- def cleanSearchers(config, searchers):
- for searcher in searchers:
- # 得到渲染好的配置文件的內容
- templateLine = Template(file(config["searcher"]["templateConfigFile"]).read()).render(
- port=searcher["port"],
- searchRoot=config["searchRoot"]
- )
- # 將渲染好的配置文件寫入一個臨時文件
- tmpConfigFile = tempfile.NamedTemporaryFile(delete=False)
- tmpConfigFile.file.write(templateLine)
- tmpConfigFile.file.close()
- # 將這個臨時文件scp拷遠程機器上的哪兒
- targetConfigFile = Template(searcher["configFile"]).render(searchRoot=config["searchRoot"])
- sftp = getSftp(searcher["host"], 22, searcher["username"], searcher["password"])
- sftp.put(tmpConfigFile.name, targetConfigFile)
- sftp.close()
- # 刪除掉之前的臨時文件
- os.remove(tmpConfigFile.name)
- # 運行啟動searcher的命令
- client = getClient(searcher["host"], 22, searcher["username"], searcher["password"])
- for command in config["searcher"]["commands"]:
- command = Template(command).render(
- searchRoot=config["searchRoot"],
- configFile=targetConfigFile,
- logConfigFile=targetLogConfigFile
- )
- client.exec_command(cmd)
- client.close()
在阿里巴巴的ISearch架構中,searchers幾行幾列是由clustermap來配置的,我們這邊也稍微簡單話一點,不考慮 merger有多臺的情況,就設計searchers幾行幾列的情況。更新一下剛才在task中的配置,加上關于clustermap的配置
|
上述是1列2行的例子,如果要配成2行2列就只要在searchers部分配成:
|
|
這樣比如1行2列渲染出來成了:
|
總結
上述就是我在測試中,對分布式環境的自動更新和批量性能測試,這樣大大減少了我們來回搗固機器、修改配置的時間。而且對測試結果的自動收集和解析也可以幫助我們來分析測試結果。我覺得這是一個不錯的嘗試,大家可以都可以試試看。
posted on 2013-01-04 14:27 順其自然EVO 閱讀(917) 評論(0) 編輯 收藏 所屬分類: 性能測試