0

我需要測試我們的應用程序中是否有任何內存泄漏,並監視內存使用量在處理請求時是否增加太多。 我正在嘗試開發一些代碼,以便對我們的api/webservice方法進行多個同時調用。此api方法不是異步的,需要一些時間才能完成操作。c#如何加載測試Web服務

我已經做了大量關於任務,線程和並行的研究,但到目前爲止我還沒有運氣。問題是,即使在嘗試了所有下面的解決方案之後,結果總是相同的,但它似乎只處理當時的兩個請求。

嘗試:

- >內創建一個簡單的任務和循環使用和不使用TaskCreationOptions.LongRunning

設置它們

啓動它們 - >內創建一個簡單的線程循環,有和沒有他們開始高優先級

- >創建的for循環的一個簡單的動作列表,並使用啓動它們

Parallel.Foreach(list, options, item => item.Invoke) 

- >直接一個的Parallel.For循環(下面)

內部運行 - >運行有和沒有選項和TPL的TaskScheduler方法

- >有用於MaxParallelism和最大線程

不同的值試圖

- >也檢查了this post,但它也沒有幫助。 (我可能會錯過什麼?)

- >檢查一些其他帖子在這裏在Stackoverflow,但與F#解決方案,我不知道如何正確地將它們轉換爲C#。 (我從來沒有使用F#...)

(從msdn拍攝任務調度器類)

這裏的基本結構,我有:

public class Test 
{ 
    Data _data; 
    String _url; 

    public Test(Data data, string url) 
    { 
     _data = data; 
     _url = url; 
    } 

    public ReturnData Execute() 
    { 
     ReturnData returnData; 

     using(var ws = new WebService()) 
     { 
       ws.Url = _url; 
       ws.Timeout = 600000; 

       var wsReturn = ws.LongRunningMethod(data); 

       // Basically convert wsReturn to my method return, with some logic if/else etc 
     } 
     return returnData; 
    } 
} 

sealed class ThreadTaskScheduler : TaskScheduler, IDisposable 
    { 
     // The runtime decides how many tasks to create for the given set of iterations, loop options, and scheduler's max concurrency level. 
     // Tasks will be queued in this collection 
     private BlockingCollection<Task> _tasks = new BlockingCollection<Task>(); 

     // Maintain an array of threads. (Feel free to bump up _n.) 
     private readonly int _n = 100; 
     private Thread[] _threads; 

     public TwoThreadTaskScheduler() 
     { 
      _threads = new Thread[_n]; 

      // Create unstarted threads based on the same inline delegate 
      for (int i = 0; i < _n; i++) 
      { 
       _threads[i] = new Thread(() => 
       { 
        // The following loop blocks until items become available in the blocking collection. 
        // Then one thread is unblocked to consume that item. 
        foreach (var task in _tasks.GetConsumingEnumerable()) 
        { 
         TryExecuteTask(task); 
        } 
       }); 

       // Start each thread 
       _threads[i].IsBackground = true; 
       _threads[i].Start(); 
      } 
     } 

     // This method is invoked by the runtime to schedule a task 
     protected override void QueueTask(Task task) 
     { 
      _tasks.Add(task); 
     } 

     // The runtime will probe if a task can be executed in the current thread. 
     // By returning false, we direct all tasks to be queued up. 
     protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued) 
     { 
      return false; 
     } 

     public override int MaximumConcurrencyLevel { get { return _n; } } 

     protected override IEnumerable<Task> GetScheduledTasks() 
     { 
      return _tasks.ToArray(); 
     } 

     // Dispose is not thread-safe with other members. 
     // It may only be used when no more tasks will be queued 
     // to the scheduler. This implementation will block 
     // until all previously queued tasks have completed. 
     public void Dispose() 
     { 
      if (_threads != null) 
      { 
       _tasks.CompleteAdding(); 

       for (int i = 0; i < _n; i++) 
       { 
        _threads[i].Join(); 
        _threads[i] = null; 
       } 
       _threads = null; 
       _tasks.Dispose(); 
       _tasks = null; 
      } 
     } 
    } 

而且測試代碼本身:

private void button2_Click(object sender, EventArgs e) 
    { 
     var maximum = 100; 
     var options = new ParallelOptions 
     { 
      MaxDegreeOfParallelism = 100, 
      TaskScheduler = new ThreadTaskScheduler() 
     }; 

     // To prevent UI blocking 
     Task.Factory.StartNew(() => 
     { 
      Parallel.For(0, maximum, options, i => 
      { 
       var data = new Data(); 
       // Fill data 
       var test = new Test(data, _url); //_url is pre-defined 
       var ret = test.Execute(); 

       // Check return and display on screen 
       var now = DateTime.Now.ToString("HH:mm:ss"); 
       var newText = $"{Environment.NewLine}[{now}] - {ret.ReturnId}) {ret.ReturnDescription}"; 

       AppendTextBox(newText, ref resultTextBox); 
      } 
    } 

    public void AppendTextBox(string value, ref TextBox textBox) 
    { 
     if (InvokeRequired) 
     { 
      this.Invoke(new ActionRef<string, TextBox>(AppendTextBox), value, textBox); 
      return; 
     } 
     textBox.Text += value; 
    } 

而我得到的結果基本上是這樣的:

[10:08:56] - (0) OK 
[10:08:56] - (0) OK 
[10:09:23] - (0) OK 
[10:09:23] - (0) OK 
[10:09:49] - (0) OK 
[10:09:50] - (0) OK 
[10:10:15] - (0) OK 
[10:10:16] - (0) OK 
etc 

據我所知,服務器端沒有限制。我對並行/多任務處理領域相對陌生。有沒有其他方法可以做到這一點?我錯過了什麼嗎?我簡化了所有代碼的清晰性,我相信所提供的代碼足以描述上述場景。我也沒有發佈應用程序代碼,但它是一個簡單的WinForms屏幕,只是爲了調用和顯示結果。如果任何代碼有某種相關性,請告訴我,我可以編輯併發布。)

在此先感謝!

EDIT1:我檢查了服務器日誌,它收到的請求兩個兩個,所以這確實是有關發送它們,沒有收到。 它可能是一個與框架如何管理請求/連接有關的網絡問題/限制嗎?或者與網絡有什麼關係(與.net無關)?

編輯2:忘了提及,它是一個SOAP web服務。

EDIT3:我發送的一個屬性(內部數據)需要爲每個請求更改。編輯4:我注意到每對請求之間總是有25秒的時間間隔,如果相關的話。

+0

您是否嘗試過使用[Web Test](https://msdn.microsoft.com/en-us/library/ms182536(v = vs.90).aspx)?您可以記錄特定的請求,然後將其作爲[VS Load Test]的一部分運行(https://www.visualstudio.com/en-us/docs/test/performance-testing/getting-started/getting-started-與性能測試)。 – G0dsquad

+0

謝謝,我沒有試過,會看看它。但我只需要測試webmethod,沒有UI。使用Web測試可以實現嗎?是否可以同時運行很多次?因爲我需要同時訪問服務器的請求,或者最接近服務器的請求。 –

+0

當然,如果WebMethod具有HTTP端點,則可以使用Web測試記錄請求(例如數據POST)。然後,您可以配置負載測試,以10分鐘的時間用真實的思考時間說50個並行用戶。 – G0dsquad

回答

2

我建議不要另起爐竈,只需使用現有的解決方案之一:

  1. 最明顯的選擇:如果您的Visual Studio許可允許,您可以使用MS負載測試框架,最有可能你贏了」噸甚至需要編寫一行代碼:How to: Create a Web Service Test
  2. SoapUI是一個自由和開源Web服務測試工具,它有一些有限的load testing capabilities
  3. 如果由於某種原因了SoapUI不適合(即你需要運行負荷測試在幾個主機或喲集羣模式您需要更多增強的報告),您可以使用Apache JMeter - 免費和開源的多協議負載測試工具,它也支持web services load testing
+0

感謝您的回覆!我編輯了這個問題,還有一件事:對於每個請求,我需要更改我發送的對象的屬性之一。我可以用這些工具來實現嗎? (我仍在閱讀文檔) –

+0

所有3個選項都可以使用,Visual Studio擁有.NET框架的所有功能,對於SoapUI和JMeter,您可以使用[Groovy語言](https://www.blazemeter。 com/blog/groovy-new-black)作爲腳本解決方案,同樣在JMeter中,您可以使用GUI配置所有內容(隨機化數據或從CSV文件,數據庫中獲取數據)。 –

+0

我設法通過在服務器上運行它,使用更強大的CPU。它看起來像我的電腦無法啓動儘可能多的線程,然後按照我的要求運行。但是這些都是一些很好的解決方案,我會在下次考慮這一點。謝謝! –

1

一個很好的解決方案來創建負載測試沒有寫一個自己的項目是使用這項服務https://loader.io/targets

它是免費的小測試,你可以POST參數,頭,...你有一個很好的報告。

+0

感謝您的迴應,但我們需要進行一些相對較大的測試,我們的測試環境不對互聯網開放。我一直在尋找更靈活/可控的東西,這就是爲什麼我們要製作自己的測試項目。 –