Skip to content

Commit 4c7de1d

Browse files
committed
- 优化 连接池不可用、定时检查;
1 parent 67b4e8f commit 4c7de1d

File tree

25 files changed

+222
-372
lines changed

25 files changed

+222
-372
lines changed

FreeSql/FreeSql.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

FreeSql/Internal/CommonProvider/AdoProvider/DbConnectionPool.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public void Return(Object<DbConnection> obj, bool isReset = false)
8888
obj.Value.Dispose();
8989
}
9090

91-
public bool SetUnavailable(Exception exception)
91+
public bool SetUnavailable(Exception exception, DateTime lastGetTime)
9292
{
9393
throw new NotImplementedException();
9494
}
@@ -109,7 +109,7 @@ public DbConnectionPoolPolicy(DbConnectionPool pool)
109109
public int AsyncGetCapacity { get; set; } = 10000;
110110
public bool IsThrowGetTimeoutException { get; set; } = true;
111111
public bool IsAutoDisposeWithSystem { get; set; } = true;
112-
public int CheckAvailableInterval { get; set; } = 5;
112+
public int CheckAvailableInterval { get; set; } = 2;
113113
public int Weight { get; set; } = 1;
114114

115115
public DbConnection OnCreate()

FreeSql/Internal/ObjectPool/DefaultPolicy.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
42
using System.Threading.Tasks;
53

64
namespace FreeSql.Internal.ObjectPool
@@ -16,7 +14,7 @@ public class DefaultPolicy<T> : IPolicy<T>
1614
public int AsyncGetCapacity { get; set; } = 10000;
1715
public bool IsThrowGetTimeoutException { get; set; } = true;
1816
public bool IsAutoDisposeWithSystem { get; set; } = true;
19-
public int CheckAvailableInterval { get; set; } = 5;
17+
public int CheckAvailableInterval { get; set; } = 2;
2018
public int Weight { get; set; } = 1;
2119

2220
public Func<T> CreateObject;

FreeSql/Internal/ObjectPool/IObjectPool.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
42
using System.Threading.Tasks;
53

64
namespace FreeSql.Internal.ObjectPool
@@ -25,8 +23,9 @@ public interface IObjectPool<T> : IDisposable
2523
/// 将对象池设置为不可用,后续 Get/GetAsync 均会报错,同时启动后台定时检查服务恢复可用
2624
/// </summary>
2725
/// <param name="exception"></param>
26+
/// <param name="lastGetTime"></param>
2827
/// <returns>由【可用】变成【不可用】时返回true,否则返回false</returns>
29-
bool SetUnavailable(Exception exception);
28+
bool SetUnavailable(Exception exception, DateTime lastGetTime);
3029

3130
/// <summary>
3231
/// 统计对象池中的对象

FreeSql/Internal/ObjectPool/Object.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
42
using System.Threading;
53

64
namespace FreeSql.Internal.ObjectPool
@@ -16,7 +14,8 @@ public static Object<T> InitWith(IObjectPool<T> pool, int id, T value)
1614
Id = id,
1715
Value = value,
1816
LastGetThreadId = Thread.CurrentThread.ManagedThreadId,
19-
LastGetTime = DateTime.Now
17+
LastGetTime = DateTime.Now,
18+
LastGetTimeCopy = DateTime.Now
2019
};
2120
}
2221

@@ -42,6 +41,7 @@ public static Object<T> InitWith(IObjectPool<T> pool, int id, T value)
4241

4342
/// 最后获取时的时间
4443
public DateTime LastGetTime { get; internal set; }
44+
public DateTime LastGetTimeCopy { get; internal set; }
4545

4646
/// <summary>
4747
/// 最后归还时的时间

FreeSql/Internal/ObjectPool/ObjectPool.cs

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Collections.Concurrent;
4-
using System.Linq;
3+
using System.Collections.Generic;
54
using System.Text;
6-
using System.Text.RegularExpressions;
75
using System.Threading;
86
using System.Threading.Tasks;
97

@@ -63,33 +61,30 @@ public partial class ObjectPool<T> : IObjectPool<T>
6361
public bool IsAvailable => this.UnavailableException == null;
6462
public Exception UnavailableException { get; private set; }
6563
public DateTime? UnavailableTime { get; private set; }
64+
public DateTime? AvailableTime { get; private set; }
6665
private object UnavailableLock = new object();
6766
private bool running = true;
6867

69-
public bool SetUnavailable(Exception exception)
68+
public bool SetUnavailable(Exception exception, DateTime lastGetTime)
7069
{
71-
7270
bool isseted = false;
73-
7471
if (exception != null && UnavailableException == null)
7572
{
76-
7773
lock (UnavailableLock)
7874
{
79-
8075
if (UnavailableException == null)
8176
{
82-
77+
if (lastGetTime < AvailableTime) return false; //已经恢复
8378
UnavailableException = exception;
8479
UnavailableTime = DateTime.Now;
80+
AvailableTime = null;
8581
isseted = true;
8682
}
8783
}
8884
}
8985

9086
if (isseted)
9187
{
92-
9388
Policy.OnUnavailable();
9489
CheckAvailable(Policy.CheckAvailableInterval);
9590
}
@@ -103,41 +98,31 @@ public bool SetUnavailable(Exception exception)
10398
/// <param name="interval"></param>
10499
private void CheckAvailable(int interval)
105100
{
106-
107101
new Thread(() =>
108102
{
109-
110103
if (UnavailableException != null)
111104
TestTrace.WriteLine($"【{Policy.Name}】Next recovery time:{DateTime.Now.AddSeconds(interval)}", ConsoleColor.DarkYellow);
112105

113106
while (UnavailableException != null)
114107
{
115-
116108
if (running == false) return;
117-
118109
Thread.CurrentThread.Join(TimeSpan.FromSeconds(interval));
119-
120110
if (running == false) return;
121111

122112
try
123113
{
124-
125114
var conn = GetFree(false);
126115
if (conn == null) throw new Exception(CoreStrings.Available_Failed_Get_Resource("CheckAvailable", this.Statistics));
127116

128117
try
129118
{
130-
131119
if (Policy.OnCheckAvailable(conn) == false) throw new Exception(CoreStrings.Available_Thrown_Exception("CheckAvailable"));
132120
break;
133-
134121
}
135122
finally
136123
{
137-
138124
Return(conn);
139125
}
140-
141126
}
142127
catch (Exception ex)
143128
{
@@ -156,61 +141,50 @@ private void RestoreToAvailable()
156141
bool isRestored = false;
157142
if (UnavailableException != null)
158143
{
159-
160144
lock (UnavailableLock)
161145
{
162-
163146
if (UnavailableException != null)
164147
{
165-
166148
UnavailableException = null;
167149
UnavailableTime = null;
150+
AvailableTime = DateTime.Now;
168151
isRestored = true;
169152
}
170153
}
171154
}
172155

173156
if (isRestored)
174157
{
175-
176158
lock (_allObjectsLock)
177159
_allObjects.ForEach(a => a.LastGetTime = a.LastReturnTime = new DateTime(2000, 1, 1));
178160

179161
Policy.OnAvailable();
180-
181162
TestTrace.WriteLine($"【{Policy.Name}】Recovered", ConsoleColor.DarkGreen);
182163
}
183164
}
184165

185166
protected bool LiveCheckAvailable()
186167
{
187-
188168
try
189169
{
190-
191170
var conn = GetFree(false);
192171
if (conn == null) throw new Exception(CoreStrings.Available_Failed_Get_Resource("LiveCheckAvailable", this.Statistics));
193172

194173
try
195174
{
196-
197175
if (Policy.OnCheckAvailable(conn) == false) throw new Exception(CoreStrings.Available_Thrown_Exception("LiveCheckAvailable"));
198-
199176
}
200177
finally
201178
{
202-
203179
Return(conn);
204180
}
205-
206181
}
207182
catch
208183
{
209184
return false;
210185
}
211186

212187
RestoreToAvailable();
213-
214188
return true;
215189
}
216190

@@ -282,7 +256,6 @@ private Object<T> GetFree(bool checkAvailable)
282256

283257
if ((_freeObjects.TryPop(out var obj) == false || obj == null) && _allObjects.Count < Policy.PoolSize)
284258
{
285-
286259
lock (_allObjectsLock)
287260
if (_allObjects.Count < Policy.PoolSize)
288261
_allObjects.Add(obj = new Object<T> { Pool = this, Id = _allObjects.Count + 1 });
@@ -310,12 +283,9 @@ private Object<T> GetFree(bool checkAvailable)
310283

311284
public Object<T> Get(TimeSpan? timeout = null)
312285
{
313-
314286
var obj = GetFree(true);
315-
316287
if (obj == null)
317288
{
318-
319289
var queueItem = new GetSyncQueueInfo();
320290

321291
_getSyncQueue.Enqueue(queueItem);
@@ -336,9 +306,7 @@ public Object<T> Get(TimeSpan? timeout = null)
336306

337307
if (obj == null)
338308
{
339-
340309
Policy.OnGetTimeout();
341-
342310
if (Policy.IsThrowGetTimeoutException)
343311
throw new TimeoutException(CoreStrings.ObjectPool_Get_Timeout(Policy.Name, "Get", timeout.Value.TotalSeconds));
344312

@@ -358,6 +326,7 @@ public Object<T> Get(TimeSpan? timeout = null)
358326

359327
obj.LastGetThreadId = Thread.CurrentThread.ManagedThreadId;
360328
obj.LastGetTime = DateTime.Now;
329+
obj.LastGetTimeCopy = DateTime.Now;
361330
Interlocked.Increment(ref obj._getTimes);
362331

363332
return obj;
@@ -367,12 +336,9 @@ public Object<T> Get(TimeSpan? timeout = null)
367336
#else
368337
async public Task<Object<T>> GetAsync()
369338
{
370-
371339
var obj = GetFree(true);
372-
373340
if (obj == null)
374341
{
375-
376342
if (Policy.AsyncGetCapacity > 0 && _getAsyncQueue.Count >= Policy.AsyncGetCapacity - 1)
377343
throw new OutOfMemoryException(CoreStrings.ObjectPool_GetAsync_Queue_Long(Policy.Name, Policy.AsyncGetCapacity));
378344

@@ -412,6 +378,7 @@ async public Task<Object<T>> GetAsync()
412378

413379
obj.LastGetThreadId = Thread.CurrentThread.ManagedThreadId;
414380
obj.LastGetTime = DateTime.Now;
381+
obj.LastGetTimeCopy = DateTime.Now;
415382
Interlocked.Increment(ref obj._getTimes);
416383

417384
return obj;
@@ -420,40 +387,31 @@ async public Task<Object<T>> GetAsync()
420387

421388
public void Return(Object<T> obj, bool isReset = false)
422389
{
423-
424390
if (obj == null) return;
425-
426391
if (obj._isReturned) return;
427392

428393
if (running == false)
429394
{
430-
431395
Policy.OnDestroy(obj.Value);
432396
try { (obj.Value as IDisposable)?.Dispose(); } catch { }
433-
434397
return;
435398
}
436399

437400
if (isReset) obj.ResetValue();
438-
439401
bool isReturn = false;
440402

441403
while (isReturn == false && _getQueue.TryDequeue(out var isAsync))
442404
{
443-
444405
if (isAsync == false)
445406
{
446-
447407
if (_getSyncQueue.TryDequeue(out var queueItem) && queueItem != null)
448408
{
449-
450409
lock (queueItem.Lock)
451410
if (queueItem.IsTimeout == false)
452411
queueItem.ReturnValue = obj;
453412

454413
if (queueItem.ReturnValue != null)
455414
{
456-
457415
obj.LastReturnThreadId = Thread.CurrentThread.ManagedThreadId;
458416
obj.LastReturnTime = DateTime.Now;
459417

@@ -469,14 +427,11 @@ public void Return(Object<T> obj, bool isReset = false)
469427

470428
try { queueItem.Dispose(); } catch { }
471429
}
472-
473430
}
474431
else
475432
{
476-
477433
if (_getAsyncQueue.TryDequeue(out var tcs) && tcs != null && tcs.Task.IsCanceled == false)
478434
{
479-
480435
obj.LastReturnThreadId = Thread.CurrentThread.ManagedThreadId;
481436
obj.LastReturnTime = DateTime.Now;
482437

@@ -509,11 +464,9 @@ public void Return(Object<T> obj, bool isReset = false)
509464

510465
public void Dispose()
511466
{
512-
513467
running = false;
514468

515469
while (_freeObjects.TryPop(out var fo)) ;
516-
517470
while (_getSyncQueue.TryDequeue(out var sync))
518471
{
519472
try { sync.Wait.Set(); } catch { }
@@ -535,13 +488,9 @@ public void Dispose()
535488

536489
class GetSyncQueueInfo : IDisposable
537490
{
538-
539491
internal ManualResetEventSlim Wait { get; set; } = new ManualResetEventSlim();
540-
541492
internal Object<T> ReturnValue { get; set; }
542-
543493
internal object Lock = new object();
544-
545494
internal bool IsTimeout { get; set; } = false;
546495

547496
public void Dispose()

0 commit comments

Comments
 (0)