我正在尝试使用StackExchange Redis库跟踪间歇性的超时“爆发”。以下是有关我们的设置的信息:我们的API用C#编写,可在Windows 2008和IIS上运行。我们在生产中有4个API服务器,并且有4台Redis机器(运行Linux最新的LTS),每台机器都有2个Redis实例(端口7000上有一个主服务器,端口7001上有一个从服务器)。我已经看过Redis服务器的几乎所有方面,它们看起来很棒。日志中没有错误,CPU和网络都很棒,服务器端的一切似乎都很奇妙。发生这种情况时,我可以tail -f
记录Redis日志,并且看不到任何异常(例如重写AOF文件或任何东西)。我不认为问题是Redis。
这是我到目前为止所知道的:
这是一个示例超时异常。大部分看起来与此几乎相同:
Type = StackExchange.Redis.RedisTimeoutException,Message =超时 执行GET limeade:allActivities,实例:1,mgr:ExecuteSelect, err:永不,队列:0,qu:0,qs:0,qc:0,wr:0,wq:0,in:0,ar:0, clientName:LIMEADEAPI4,serverEndpoint:10.xx.xx.11:7000, keyHashSlot:1295,IOCP:(Busy = 0,Free = 1000,Min = 2,Max = 1000),工作人员: (繁忙= 9,免费= 32758,最小值= 2,最大值= 32767)(请看一下 关于可能导致超时的一些常见客户端问题的文章: http://stackexchange.github.io/StackExchange.Redis/Timeouts),StackTrace= 在 StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl [T](消息 消息,ResultProcessor
中的cacheKey,CacheItemVersion&cacheItemVersion)1 processor, ServerEndPoint server) at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor
1个处理器,ServerEndPoint服务器)位于 StackExchange.Redis.RedisBase.ExecuteSync [T](消息, ResultProcessor1 processor, ServerEndPoint server) at StackExchange.Redis.RedisDatabase.StringGet(RedisKey key, CommandFlags flags) at Limeade.Caching.Providers.RedisCacheProvider
1.Get [T](K ...
我已经对跟踪这些超时异常进行了一些研究,但是令人惊讶的是所有数字都为零。队列中没有任何东西,没有任何等待处理的东西,我有大量线程可用,什么也没做。一切看起来都很好。
有人对如何解决此问题有任何想法吗?问题是这些高速缓存超时突发会导致我们的数据库受到更多的攻击,在某些情况下,这是一件坏事。我很高兴添加任何其他任何对您有帮助的信息。
更新:连接代码
连接到Redis的代码是一个相当复杂的系统的一部分,该系统支持各种缓存环境和配置,但是我可能可以将其归结为基本知识。首先,有一个CacheFactory
类:
public class CacheFactory : ICacheFactory
{
private static readonly ILogger log = LoggerManager.GetLogger(typeof(CacheFactory));
private static readonly ICacheProvider<CacheKey> cache;
static CacheFactory()
{
ICacheFactory<CacheKey> configuredFactory = CacheFactorySection.Current?.CreateConfiguredFactory<CacheKey>();
if (configuredFactory == null)
{
// Some error handling, not important
}
cache = configuredFactory.GetDefaultCache();
}
// ...
}
ICacheProvider
是实现与特定缓存系统进行对话的方法,可以对其进行配置。在这种情况下,configureFactory是一个RedisCacheFactory
,看起来像这样:
public class RedisCacheFactory<T> : ICacheFactory<T> where T : CacheKey, ICacheKeyRepository
{
private RedisCacheProvider<T> provider;
private readonly RedisConfiguration configuration;
public RedisCacheFactory(RedisConfiguration config)
{
this.configuration = config;
}
public ICacheProvider<T> GetDefaultCache()
{
return provider ?? (provider = new RedisCacheProvider<T>(configuration));
}
}
GetDefaultCache
方法在静态构造函数中被调用一次,并返回一个RedisCacheProvider
。此类实际上是与Redis关联的:
public class RedisCacheProvider<K> : ICacheProvider<K> where K : CacheKey, ICacheKeyRepository
{
private readonly ConnectionMultiplexer redisConnection;
private readonly IDatabase db;
private readonly RedisCacheSerializer serializer;
private static readonly ILog log = Logging.RedisCacheProviderLog<K>();
private readonly CacheMonitor<K> cacheMonitor;
private readonly TimeSpan defaultTTL;
private int connectionErrors;
public RedisCacheProvider(RedisConfiguration options)
{
redisConnection = ConnectionMultiplexer.Connect(options.EnvironmentOverride ?? options.Connection);
db = redisConnection.GetDatabase();
serializer = new RedisCacheSerializer(options.SerializationBinding);
cacheMonitor = new CacheMonitor<K>();
defaultTTL = options.DefaultTTL;
IEnumerable<string> hosts = options.Connection.EndPoints.Select(e => (e as DnsEndPoint)?.Host);
log.InfoFormat("Created Redis ConnectionMultiplexer connection. Hosts=({0})", String.Join(",", hosts));
}
// ...
}
构造函数基于已配置的Redis端点(位于某些配置文件中)创建ConnectionMultiplexer。每次创建连接时,我也会记录日志。我们看不到这些日志语句过多,并且与Redis的连接保持稳定。
答案 0 :(得分:0)
在global.asax
中,尝试添加:
protected void Application_Start(object sender, EventArgs e)
{
ThreadPool.SetMinThreads(200, 200);
}
对于我们来说,这将错误从每天〜50-100减少到了零。我认为设置数字取决于系统是没有一般性规定的(200个对我们有用),因此可能需要您做些尝试。
我也相信这可以改善网站的性能。