Skip to content

Commit

Permalink
- 增加 autoDispose 参数配置,禁止自动释放;#264 #198 #179
Browse files Browse the repository at this point in the history
  • Loading branch information
28810 authored and 28810 committed Mar 20, 2020
1 parent 3739f98 commit 72ed615
Show file tree
Hide file tree
Showing 11 changed files with 895 additions and 7 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ var csredis = new CSRedis.CSRedisClient("127.0.0.1:6379,password=123,defaultData
| poolsize | 50 | 连接池大小 |
| connectTimeout | 5000 | 连接超时设置(毫秒) |
| syncTimeout | 10000 | 发送/接收超时设置(毫秒) |
| idleTimeout | 0 | 连接池内元素空闲时间(毫秒),适用连接远程redis-server |
| idleTimeout | 20000 | 连接池内元素空闲时间(毫秒),适用连接远程redis-server |
| preheat | true | 预热连接,接收数值如 preheat=5 预热5个连接 |
| autoDispose | true | 跟随项目自动释放,监听 AppDomain.CurrentDomain.ProcessExit/Console.CancelKeyPress 事件 |
| ssl | false | 是否开启加密传输 |
| testcluster | true | 是否尝试集群模式,阿里云、腾讯云集群需要设置此选项为 false |
| writeBuffer | 10240 | 异步方法写入缓冲区大小(字节) |
Expand Down
2 changes: 1 addition & 1 deletion src/CSRedisClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using SafeObjectPool;
using CSRedus.Internal.ObjectPool;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
Expand Down
2 changes: 1 addition & 1 deletion src/CSRedisClientAsync.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using SafeObjectPool;
using CSRedus.Internal.ObjectPool;
using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand Down
2 changes: 1 addition & 1 deletion src/CSRedisClientPipe.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using SafeObjectPool;
using CSRedus.Internal.ObjectPool;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
Expand Down
3 changes: 1 addition & 2 deletions src/CSRedisCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<AssemblyName>CSRedisCore</AssemblyName>
<PackageId>CSRedisCore</PackageId>
<RootNamespace>CSRedisCore</RootNamespace>
<Version>3.4.5</Version>
<Version>3.5.0</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageProjectUrl>https://github.com/2881099/csredis</PackageProjectUrl>
<Description>CSRedis 是 redis.io 官方推荐库,支持 redis-trib集群、哨兵、私有分区与连接池管理技术,简易 RedisHelper 静态类。</Description>
Expand All @@ -25,7 +25,6 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="SafeObjectPool" Version="2.3.1" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net40'">
Expand Down
75 changes: 75 additions & 0 deletions src/Internal/ObjectPool/DefaultPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace CSRedus.Internal.ObjectPool
{

public class DefaultPolicy<T> : IPolicy<T>
{

public string Name { get; set; } = typeof(DefaultPolicy<T>).GetType().FullName;
public int PoolSize { get; set; } = 1000;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(50);
public int AsyncGetCapacity { get; set; } = 10000;
public bool IsThrowGetTimeoutException { get; set; } = true;
public bool IsAutoDisposeWithSystem { get; set; } = true;
public int CheckAvailableInterval { get; set; } = 5;

public Func<T> CreateObject;
public Action<Object<T>> OnGetObject;

public T OnCreate()
{
return CreateObject();
}

public void OnDestroy(T obj)
{

}

public void OnGet(Object<T> obj)
{
//Console.WriteLine("Get: " + obj);
OnGetObject?.Invoke(obj);
}

#if net40
#else
public Task OnGetAsync(Object<T> obj)
{
//Console.WriteLine("GetAsync: " + obj);
OnGetObject?.Invoke(obj);
return Task.FromResult(true);
}
#endif

public void OnGetTimeout()
{

}

public void OnReturn(Object<T> obj)
{
//Console.WriteLine("Return: " + obj);
}

public bool OnCheckAvailable(Object<T> obj)
{
return true;
}

public void OnAvailable()
{

}

public void OnUnavailable()
{

}
}
}
63 changes: 63 additions & 0 deletions src/Internal/ObjectPool/IObjectPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace CSRedus.Internal.ObjectPool
{
public interface IObjectPool<T> : IDisposable
{
IPolicy<T> Policy { get; }
/// <summary>
/// 是否可用
/// </summary>
bool IsAvailable { get; }
/// <summary>
/// 不可用错误
/// </summary>
Exception UnavailableException { get; }
/// <summary>
/// 不可用时间
/// </summary>
DateTime? UnavailableTime { get; }

/// <summary>
/// 将对象池设置为不可用,后续 Get/GetAsync 均会报错,同时启动后台定时检查服务恢复可用
/// </summary>
/// <param name="exception"></param>
/// <returns>由【可用】变成【不可用】时返回true,否则返回false</returns>
bool SetUnavailable(Exception exception);

/// <summary>
/// 统计对象池中的对象
/// </summary>
string Statistics { get; }
/// <summary>
/// 统计对象池中的对象(完整)
/// </summary>
string StatisticsFullily { get; }

/// <summary>
/// 获取资源
/// </summary>
/// <param name="timeout">超时</param>
/// <returns></returns>
Object<T> Get(TimeSpan? timeout = null);

#if net40
#else
/// <summary>
/// 获取资源
/// </summary>
/// <returns></returns>
Task<Object<T>> GetAsync();
#endif

/// <summary>
/// 使用完毕后,归还资源
/// </summary>
/// <param name="obj">对象</param>
/// <param name="isReset">是否重新创建</param>
void Return(Object<T> obj, bool isReset = false);
}
}
104 changes: 104 additions & 0 deletions src/Internal/ObjectPool/IPolicy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace CSRedus.Internal.ObjectPool
{
public interface IPolicy<T>
{

/// <summary>
/// 名称
/// </summary>
string Name { get; set; }

/// <summary>
/// 池容量
/// </summary>
int PoolSize { get; set; }

/// <summary>
/// 默认获取超时设置
/// </summary>
TimeSpan SyncGetTimeout { get; set; }

/// <summary>
/// 空闲时间,获取时若超出,则重新创建
/// </summary>
TimeSpan IdleTimeout { get; set; }

/// <summary>
/// 异步获取排队队列大小,小于等于0不生效
/// </summary>
int AsyncGetCapacity { get; set; }

/// <summary>
/// 获取超时后,是否抛出异常
/// </summary>
bool IsThrowGetTimeoutException { get; set; }

/// <summary>
/// 监听 AppDomain.CurrentDomain.ProcessExit/Console.CancelKeyPress 事件自动释放
/// </summary>
bool IsAutoDisposeWithSystem { get; set; }

/// <summary>
/// 后台定时检查可用性间隔秒数
/// </summary>
int CheckAvailableInterval { get; set; }

/// <summary>
/// 对象池的对象被创建时
/// </summary>
/// <returns>返回被创建的对象</returns>
T OnCreate();

/// <summary>
/// 销毁对象
/// </summary>
/// <param name="obj">资源对象</param>
void OnDestroy(T obj);

/// <summary>
/// 从对象池获取对象超时的时候触发,通过该方法统计
/// </summary>
void OnGetTimeout();

/// <summary>
/// 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
/// </summary>
/// <param name="obj">资源对象</param>
void OnGet(Object<T> obj);
#if net40
#else
/// <summary>
/// 从对象池获取对象成功的时候触发,通过该方法统计或初始化对象
/// </summary>
/// <param name="obj">资源对象</param>
Task OnGetAsync(Object<T> obj);
#endif

/// <summary>
/// 归还对象给对象池的时候触发
/// </summary>
/// <param name="obj">资源对象</param>
void OnReturn(Object<T> obj);

/// <summary>
/// 检查可用性
/// </summary>
/// <param name="obj">资源对象</param>
/// <returns></returns>
bool OnCheckAvailable(Object<T> obj);

/// <summary>
/// 事件:可用时触发
/// </summary>
void OnAvailable();
/// <summary>
/// 事件:不可用时触发
/// </summary>
void OnUnavailable();
}
}
93 changes: 93 additions & 0 deletions src/Internal/ObjectPool/Object.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace CSRedus.Internal.ObjectPool
{

public class Object<T> : IDisposable
{
public static Object<T> InitWith(IObjectPool<T> pool, int id, T value)
{
return new Object<T>
{
Pool = pool,
Id = id,
Value = value,
LastGetThreadId = Thread.CurrentThread.ManagedThreadId,
LastGetTime = DateTime.Now
};
}

/// <summary>
/// 所属对象池
/// </summary>
public IObjectPool<T> Pool { get; internal set; }

/// <summary>
/// 在对象池中的唯一标识
/// </summary>
public int Id { get; internal set; }
/// <summary>
/// 资源对象
/// </summary>
public T Value { get; internal set; }

internal long _getTimes;
/// <summary>
/// 被获取的总次数
/// </summary>
public long GetTimes => _getTimes;

/// 最后获取时的时间
public DateTime LastGetTime { get; internal set; }

/// <summary>
/// 最后归还时的时间
/// </summary>
public DateTime LastReturnTime { get; internal set; }

/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; internal set; } = DateTime.Now;

/// <summary>
/// 最后获取时的线程id
/// </summary>
public int LastGetThreadId { get; internal set; }

/// <summary>
/// 最后归还时的线程id
/// </summary>
public int LastReturnThreadId { get; internal set; }

public override string ToString()
{
return $"{this.Value}, Times: {this.GetTimes}, ThreadId(R/G): {this.LastReturnThreadId}/{this.LastGetThreadId}, Time(R/G): {this.LastReturnTime.ToString("yyyy-MM-dd HH:mm:ss:ms")}/{this.LastGetTime.ToString("yyyy-MM-dd HH:mm:ss:ms")}";
}

/// <summary>
/// 重置 Value 值
/// </summary>
public void ResetValue()
{
if (this.Value != null)
{
try { this.Pool.Policy.OnDestroy(this.Value); } catch { }
try { (this.Value as IDisposable)?.Dispose(); } catch { }
}
T value = default(T);
try { value = this.Pool.Policy.OnCreate(); } catch { }
this.Value = value;
this.LastReturnTime = DateTime.Now;
}

internal bool _isReturned = false;
public void Dispose()
{
Pool?.Return(this);
}
}
}
Loading

0 comments on commit 72ed615

Please sign in to comment.