本身動手寫壓力測試-三劍客HttpClient+Async+Parallel

曾經滄海難爲水 php

信息如水 壓力如潮

功能實現階段,咱們對得要處理的信息分析得很細緻,很透徹,所謂細如絲,透如水。然而,到了產品的階段,要處理的信息卻如同潮洪而至,本來的假設預想,統統被擊成了碎片。這時候產生的錯誤和問題,很難在開發機上重現。 html

若是說用戶驗收測試是對功能實現的檢查,須要滴水不漏;壓力測試則是容量的考驗,迎接浪的洗禮。 node

(本文版權屬於© 2012 - 2013 予沁安apache

環肥燕瘦

壓力測試的工具頗多,尤爲是HP的LoadRunner甚至成爲了行業標準。但是,在研究和考察的過程當中,內心卻慢慢有了質疑,我是否非得用這些工具嗎? 一則,它們是商業軟件,價格不菲;二則,仍是由於是商業軟件,功能太多,太龐大,不少東西我都不須要。爲何不本身作一個簡單實用的呢? 編程

小趙研究Selenium時,我以爲用他用的語法很貼近業務語言,因而我提出一個問題,能夠用於壓力測試嗎?他說不行,由於Selenium是要徹底啓動瀏覽器。平時,看起來瘦小的瀏覽器,其實很耗資源,特別是與壓力測試的容量來比,瀏覽器是個徹徹底底的大胖子。你能夠試一下,在你的機器上同時開啓100個瀏覽窗口,會是個什麼情況。 瀏覽器

苗條美人 HttpClient

否認了Selenium以後,很快就找到了個人目標HttpClient (其實還有個前生WebClient,後面有敘)。從名稱,咱們就能夠知道,它已經定位到很低Http層,這一層是效率與易用的一個最佳平衡點。可是,它是.Net 4.5下的部件,在.Net 4.0必須用NuGet來下載。 網絡

查看了不少資料之後,我能夠確信,HttpClient正是我想要的。她還有一個很大的特點,徹底只提供異步接口。這其實是另外一種大瘦身,耗用資源上的瘦身,HttpClient正式我要的窈窕淑女。 app

前生:WebClient 框架

var values = new NameValueCollection();
foreach (var key_value in ui.FormData)
{
	values.Add(key_value.Key, key_value.Value);
}
var client = new WebClient();
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
Console.WriteLine(string.Concat(base_site + ui.Path, ui.Method.ToString().ToLower(), values));
byte[] result = client.UploadValues(base_site + ui.Path, ui.Method.ToString().ToLower(), values);
string ResultAuthTicket = Encoding.UTF8.GetString(result);
Console.WriteLine(client.BaseAddress);
Console.WriteLine(client.ResponseHeaders.ToString());
Console.WriteLine(ResultAuthTicket);

HttpClient的Async方法,注意最後的Wait()有把異步轉化爲了同步 異步

var form_data=new Dictionary<string, string>();
form_data.Add("system_account","test1@skight.com");
form_data.Add("system_password","123456");
var values = new NameValueCollection();
foreach (var key_value in form_data)
{
	values.Add(key_value.Key, key_value.Value);
}
var client = new HttpClient();

client.GetStringAsync("http://esr20syst.skight.com/District/03/UserLogin.do")
	  .ContinueWith(
		  t =>
		  {
			  Console.WriteLine("Time {0}", DateTime.Now);
			  Console.WriteLine(t.Result);
		  })
	  .Wait();

Sync 仍是Async 這,是一個問題

.Net 4,5 出來以後,一直沒有對它的新功能和特性太在乎。只是公司升級使用VS2012,除了灰不溜秋的界面,而所謂的性能提升(其實,是VS2010太次)以外,也沒有特別感受。

然而,此次在查看HttpClient資料時,卻意外發現了.Net 4.5 語法級別的一個亮點: Asyn和Await。這讓異步編程更簡便,更漂亮。看來,從此異步編程是一個大潮流,微軟也不惜餘力。

新語法應用以後的效果,彷佛和平時的同步編碼沒有太大區別,除了不時冒出來的Await和Async

var form_data=new Dictionary<string, string>();
form_data.Add("system_account","test1@skight.com");
form_data.Add("system_password","123456");
foreach (var key_value in form_data)
{
	values.Add(key_value.Key, key_value.Value);
}
var httpClient = new HttpClient();
var content= await httpClient.GetStringAsync("http://esr20syst.skight.com/District/03/UserLogin.do");
Console.WriteLine(content.Result);

異步性能的福利是不可隨小覷的。以前,有Node.js構建的的Web服務比Apache快不少(http://zgadzaj.com/benchmarking-nodejs-basic-performance-tests-against-apache-php)就是得益於Javascript天生的函數回調方式支持的異步運行。如今有.Net對Async的友好支持,以及大量組件基於異步方式的重寫。聽說,微軟推薦,凡是運行時間超過20毫秒的功能,就要用異步方式來寫。HttpClient就是一個例子,它的前身WebClient就不具異步調用,而HttpClient乾脆就不提供同步接口。

平行宇宙 Parallel

其實,不管是的Async仍是Parallel,都是語法糖,但是做爲辛苦的開發者,咱們好的就是這一口。

Async讓咱們發出網絡請沒必要再等待,Parallel讓咱們很容易的持續發出平行請求,這就是一個徹底的壓力測試模型了。我這裏簡單設置了一個100 * 10 個請求。沒有具體計算,共發出多少個請求,我只知道,多得已經足夠讓個人系統重現產品機上的問題了。

Parallel.For(1, 1000, i =>
	Parallel.For(1, 5, case_number =>
	   LoginScenario(case_number)
		   .run_by(runner)
	));

:個人業務語法糖DSL

這裏是我對系統頁面操做的定義代碼,用語法糖DSL的方式實現,必定程度上實現了需求即代碼即文檔的要求吧。這部分代碼不能直接運行,由於它使用了我本身的Web框架,從而能夠用強類型自動生成URL。這裏提供出來只是做參考,做爲示例的一部分。

private static Scenario LoginScenario(int case_number)
{
	return
		UI.context(Keys.Context.District.with_value(DistrictIdentifier.of("03")))
		  .to<UserLoginGet>()
		  .then(
			  UI.input(SystemPayloadKeys.Account.with_value(string.Format("test{0}@skight.com", case_number)))
				.and_input(SystemPayloadKeys.Password.with_value("123456"))
				.to<UserLoginPost>());
}

(本文版權屬於© 2012 - 2013 予沁安 | 轉載請註明做者和出處

相關文章
相關標籤/搜索