背景介紹
最近遇到國密改造的性能測試項目,有點小趣:
- 服務處理邏輯
伺服器收到封包,調用動态庫,根據封包中多個字段,動态計算出一個值,再與封包某個字段進行對比校驗,若校驗通過則認為封包合法,不通過則拒絕服務。我們把對比字段稱為校驗字段,多個字段稱為計算字段。
- 思路曆程
首先,考慮在測試的接口不多,為減少測試的複雜性,想到對封包中的字段進行固化,進而達到校驗字段不變的目的。
帶着想法找到開發人員看看封包的計算字段有哪些,是否有字段影響測試的準确性。
果不其然,這是不行的。每類封包的“計算字段”有可能不同,且同類封包中,字段A或字段B的固化變導緻資料庫的熱點問題。開發人員建議傳入整個封包到加密庫,線上也是如此。
考慮到開發意見,決定JMeter發送封包前調用加密庫對封包進行更新。
- 細項考量
與開發約定,開發提供一個Jar包(封裝加密庫的實作細節),且Bytes和String傳入參數類型統一約定為String。
根據開發人員提供的對Jar的測試代碼,實作對Tcp Sampler的小改。
TCP Sampler的小改
這是開發提供的對Jar包的測試代碼:
public class MacTest {
public static void main(String[] args) {
MacGenerator mg = new MacGenerator();
//String secKey = "111111111111111111111111111111111"; //A用
String secKey="22222222222222222222"; //B用
String testStr = "this is a message";
testStr = mg.genMac(testStr, secKey);
System.out.println(testStr);
}
}
很簡單的代碼,生成一個執行個體,再調用執行個體方法,傳入“封包”和“KEY"值即可。
上述經在測試環境驗證成功後,參考我之前在知乎上寫過相于
動态封包長度的處理方法。更改TCP Sampler實作如下:
import ...;
public class prelenTCPWithMacUpdateImpl extends TCPClientImpl {
//存在其他私有成員,不重要,為減少文章長度,忽略
//在user.properties裡配置KEY值
private final String secKey = JMeterUtils.getPropDefault("tcp.cipher_cn.secKey", "0");
public prelenTCPWithMacUpdateImpl() {
super();
}
@Override
public void write(OutputStream os, String s) throws IOException {
//這是新增代碼的開始
MacGenerator mg = new MacGenerator();
String strWithMacVal = mg.genMac(s, this.secKey);
//這裡新增代碼的結束
//這是”動态封包長度“的小改開始
byte[] sb = strWithMacVal.getBytes(CHARSET);
ByteBuffer bb = ByteBuffer.allocate(sb.length + this.lengthPrefixLen);
String headStr = Integer.toString(sb.length);
int len = headStr.length();
byte[] prefixCharByte = this.prefixChar.getBytes(CHARSET);
if(prefixCharByte.length != 1) {
log.error("prefixCharByte.length not is 1:" + prefixCharByte.length);
return;
}
for(int i=0; i<this.lengthPrefixLen - len; i++) {
bb.put(prefixCharByte);
}
bb.put(headStr.getBytes(CHARSET));
bb.put(sb);
if(log.isDebugEnabled()) {
//不重要,為減少文章長度,忽略
}
//這是”動态封包長度“的小改結束
os.write(bb.array());
os.flush();
}
private String showEOL(final String input) {
//不重要,為減少文章長度,忽略
}
}
更改後,重新編輯打包,和開發提供的Jar包,一起放入$JMETER_HOME/lib/ext目錄裡,同時在user.properties配置tcp.cipher_cn.secKey和jmeter tcp.handler。
到這裡差不多完成了,還差一個,讓JMeter的運作環境可以找到我們的加密庫,參考開發給的運作代碼:
java -Djava.library.path=/dir_path/加密庫檔案 -cp ./xxxx.jar:./ 開發給的測試代碼
因我的JMeter在linux環境下運作,故更改$JMETER_HOME/bin/jmeter檔案最後一行,如下:
MAC_OPTS="-Djava.library.path=/dir_path/加密庫檔案"
"$JAVA_HOME/bin/java" $ARGS $JVM_ARGS $JMETER_OPTS $MAC_OPTS -jar "$PRGDIR/ApacheJMeter.jar" "$@"
最後的唠叨
- 上述更改,可成功的實作我們的目的,即JMeter調用加密庫更新字段。
- 這樣的更改不算難,甚至很簡單,作性能測試,無論是壓測工具,還是輔助測試的代碼,這是達到測試目的的過程而已。
- 上述的過程,我們大約需要了解下述幾點:
- 基礎的java知識點。
- 對JMeter的TCP Sampler源碼有所了解。
- 對JMeter的啟動引導有所了解。
- 和開發的溝通協調。