程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 如何簡易的提高吞吐量,簡易提高吞吐量

如何簡易的提高吞吐量,簡易提高吞吐量

編輯:C#入門知識

如何簡易的提高吞吐量,簡易提高吞吐量


    性能提升還是那幾個要素,就像我在之前的博文裡面提到的一樣,這一篇只是更加簡單一點而已。

    因為硬件配置是固定的,那我們只是簡單說一說在使用C#進行開發的項目中,如何使用一些簡單的小招數讓性能有一個比較大幅度的顯著提升。

    一、繞開那些煩人卻又不可避免的DB操作。

    DB操作是不可避免卻又是項目重中之中的所在,那我們可以做哪些優化呢?

    首先,根據業務將DB操作分為需要即時和非即時的兩塊,關於非即時的我們可以將其單獨的交給某一個線程來單獨慢慢處理。代碼如下:

public class DbActionQueue : IDisposable { public Queue<Action> _transQueue; private Thread _thread; private bool _isDispose = false; private static readonly object _syncObject = new object(); private readonly object _syncQueueObject = new object(); private static DbActionQueue _instance; public static DbActionQueue Instance { get { if (_instance == null) { lock (_syncObject) { if (_instance == null) { _instance = new DbActionQueue(); } } } return _instance; } } private DbActionQueue() { if (_transQueue == null) { _transQueue = new Queue<Action>(); } if (_thread == null) { _thread = new Thread(Thread_Work) { IsBackground = true }; } _thread.Start(); } public void Push(Action action) { if (_transQueue == null) throw new ArgumentNullException("dbActionQueue is not init"); lock (_syncQueueObject) { _transQueue.Enqueue(action); } } public void Thread_Work() { while (!_isDispose) { Action[] items = null; if (_transQueue != null && _transQueue.Count > 0) { lock (_syncQueueObject) { items = new Action[_transQueue.Count]; _transQueue.CopyTo(items, 0); _transQueue.Clear(); } } if (items != null && items.Length > 0) { foreach (var item in items) { try { item.Invoke(); } catch (Exception ex) { LogHelper.Write(string.Format("DbActionQueue error. | Exception.StackTrace:{0}", ex.StackTrace), ex); } } } Thread.Sleep(1); } } public void Dispose() { _isDispose = true; _thread.Join(); } } View Code

    通過代碼可以看到,我們在實例化的時候,單獨創建了一個線程,用來做處理。

    那對於一些像日志之類的操作,則可以通過以下代碼進行操作:

DbActionQueue.Instance.Push(() => { LogBLL.Instance.Add(new Log { action_time = DateTime.Now; }); }); View Code

    到這裡不難免要問了,如果數據量過大,單個隊列已經無法滿足的時候,怎麼做處理。關於隊列的監控,優化不在該文討論,通俗一點的做法可以引入一些第三方的隊列。另外在項目中,其實我們更多的時候,實際上並不是在Insert,Update,Delete等操作,而是Select的操作,那關於Select的一些緩存處理,也不在該文的討論范疇,因為關於Cache的各種中間件實在太多,而且篇幅太大。

    可能在某些時候,我們還是覺得單個線程處理太慢,希望多開幾個線程來處理對於DB的請求,則我們可以根據實際業務情況和機器配置,初始化任意個線程來處理,則以上代碼需要稍稍改裝一下,將單例的換成可自由實例化的,代碼如下:

public class DbQueue { public Queue<Action> _transQueue; private Thread _thread; private bool _isDispose = false; private readonly object _syncQueueObject = new object(); public DbQueue() { if (_transQueue == null) { _transQueue = new Queue<Action>(); } if (_thread == null) { _thread = new Thread(Thread_Work) { IsBackground = true }; } _thread.Start(); } public void Thread_Work() { while (!_isDispose) { Action[] items = null; if (_transQueue != null && _transQueue.Count > 0) { lock (_syncQueueObject) { items = new Action[_transQueue.Count]; _transQueue.CopyTo(items, 0); _transQueue.Clear(); } } if (items != null && items.Length > 0) { foreach (var item in items) { try { item.Invoke(); } catch (Exception ex) { LogHelper.Write(string.Format("DbActionQueue error. | Exception.StackTrace:{0}", ex.StackTrace), ex); } } } Thread.Sleep(1); } } public void Push(Action action) { if (_transQueue == null) throw new ArgumentNullException("dbActionQueue is not init"); lock (_syncQueueObject) { _transQueue.Enqueue(action); } } public void Dispose() { _isDispose = true; _thread.Join(); } } View Code

 那多個線程之間的處理,代碼則如下:

public class DbQueueManage { private int _threadNumber = 2; private DbQueue[] _dbQueues; private Random random = new Random(); private DbQueueManage() { } static DbQueueManage() { } private static readonly object _syncObject = new object(); private static DbQueueManage _instance; public static DbQueueManage Instance { get { if (_instance == null) { lock (_syncObject) { if (_instance == null) { _instance = new DbQueueManage(); } } } return _instance; } } public void Init(Action action, int threadNum = 2) { if (_dbQueues == null) { this._threadNumber = threadNum; _dbQueues = new DbQueue[threadNum]; for (var i = 0; i < threadNum; i++) { _dbQueues[i] = new DbQueue(); } } } public void Push(Action action) { var index = GetRandomThreadIndex(); if (_dbQueues != null && _dbQueues.Length > index) { _dbQueues[index].Push(action); } } public int GetRandomThreadIndex() { return random.Next(0, this._threadNumber); } } View Code

另外關於為什麼不選用Task來做處理,雖然Task關於線程的處理還是很優秀的,這裡請各位同僚自行定奪。關於即時性的DB操作,則可以以Redis,MongoDb,或者自行編寫的緩存來作為中間件,然後再講具體入庫的操作,放入之前編寫好的隊列處理裡面。

    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved