掃碼支付接口將要上線钠惩,近幾天在優(yōu)化系統(tǒng)性能。昨天把日志Helper類的日志記錄改成了使用Queue<T>對象來實現(xiàn)異步處理族阅。
做了單元測試篓跛,并模擬多線程來測試,是快了不少坦刀。
今天將站點部署到準生產環(huán)境愧沟,用loadrunner壓測時,發(fā)現(xiàn)運行一段時間后報如下異常鲤遥,并且導致iis進程掛掉:
2017/2/16 11:50:08 [ClientPayAPI_115007438_1CD2C]酷寶獲取二維碼異常:System.ArgumentException: 目標數(shù)組的長度不夠沐寺。請檢查 destIndex 和長度以及數(shù)組的下限。
在 System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
在 System.Collections.Generic.Queue`1.SetCapacity(Int32 capacity)
在 System.Collections.Generic.Queue`1.Enqueue(T item)
在 CommonUtils.LogHelper.InputFile(String log, LogType logType)
在 CommonUtils.LogHelper.Write(String logText)
在 PaymentBLL.HttpMessageSignService.ValidPayRequestSign_New(String requestJson)
在 PaymentPlatform.Kubao.QuickPay.ClientPayAPI.ExecFun_New(String request)
在 PaymentPlatform.Kubao.QuickPay.ClientPayAPI.ProcessRequest(HttpContext context)
本地再次模擬高并發(fā)測試盖奈,發(fā)現(xiàn)復現(xiàn)的幾率很小混坞。不過,無論如何卜朗,既然好在可以復現(xiàn)拔第,就要解決。
經查场钉,Queue<T>以及List<T>不是線程安全的蚊俺。在并發(fā)操作時,內部操作可能會出現(xiàn)問題逛万。通過ILSpy(.Net 反編譯軟件泳猬,可以打開.NET 的exe和DLL等程序集批钠,前提要求程序集未加密/未加殼/未做強度混淆),或者去微軟官方(referencesource.microsoft.com得封,.net 已經開源了)可以查看Enqueue方法的實現(xiàn)埋心,可知并未控制并發(fā)。
#region 程序集 mscorlib.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll
#endregion
// Adds item to the tail of the queue.
//
/// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Enqueue"]/*' />
public void Enqueue(T item) {
if (_size == _array.Length) {
int newcapacity = (int)((long)_array.Length * (long)_GrowFactor / 100);
if (newcapacity < _array.Length + _MinimumGrow) {
newcapacity = _array.Length + _MinimumGrow;
}
SetCapacity(newcapacity);
}
_array[_tail] = item;
_tail = (_tail + 1) % _array.Length;
_size++;
_version++;
}
對此問題忙上,解決方案有2個:
【方案一】入隊時使用并發(fā)鎖lock拷呆。
【方案二】使用ConcurrentQueue<T>。ConcurrentQueue<T>表示線程安全的先進先出 (FIFO) 集合疫粥。這個類在.net類庫的System.Collections.Concurrent下茬斧。System.Collections.Concurrent命名空間提供多個線程安全集合類。當有多個線程并發(fā)訪問集合時梗逮,應使用這些類來代替System.Collections和System.Collections.Generic命名空間中的對應類型项秉。