我正在使用 ServiceStack.Redis 实现来缓存通过 Web API 接口传递的事件。这些事件应该被插入缓存并在一段时间后自动删除(例如 3 天):
private readonly IRedisTypedClient<CachedMonitoringEvent> _eventsCache;
public EventMonitorCache([NotNull]IRedisTypedClient<CachedMonitoringEvent> eventsCache)
{
_eventsCache = eventsCache;
}
public void Dispose()
{
//Release connections again
_eventsCache.Dispose();
}
public void AddOrUpdate(MonitoringEvent monitoringEvent)
{
if (monitoringEvent == null)
return;
try
{
var cacheExpiresAt = DateTime.Now.Add(CacheExpirationDuration);
CachedMonitoringEvent cachedEvent;
string eventKey = CachedMonitoringEvent.CreateUrnId(monitoringEvent);
if (_eventsCache.ContainsKey(eventKey))
{
cachedEvent = _eventsCache[eventKey];
cachedEvent.SetExpiresAt(cacheExpiresAt);
cachedEvent.MonitoringEvent = monitoringEvent;
}
else
cachedEvent = new CachedMonitoringEvent(monitoringEvent, cacheExpiresAt);
_eventsCache.SetEntry(eventKey, cachedEvent, CacheExpirationDuration);
}
catch (Exception ex)
{
Log.Error("Error while caching MonitoringEvent", ex);
}
}
public List<MonitoringEvent> GetAll()
{
IList<CachedMonitoringEvent> allEvents = _eventsCache.GetAll();
return allEvents
.Where(e => e.MonitoringEvent != null)
.Select(e => e.MonitoringEvent)
.ToList();
}
StructureMap 3 注册表如下所示:
public class RedisRegistry : Registry
{
private readonly static RedisConfiguration RedisConfiguration = Config.Feeder.Redis;
public RedisRegistry()
{
For<IRedisClientsManager>().Singleton().Use(BuildRedisClientsManager());
For<IRedisTypedClient<CachedMonitoringEvent>>()
.AddInstances(i => i.ConstructedBy(c => c.GetInstance<IRedisClientsManager>()
.GetClient().GetTypedClient<CachedMonitoringEvent>()));
}
private static IRedisClientsManager BuildRedisClientsManager()
{
return new PooledRedisClientManager(RedisConfiguration.Host + ":" + RedisConfiguration.Port);
}
}
第一个场景是检索所有缓存的事件(数百个)并通过 ODataV3 和 ODataV4 将其传递到 Excel PowerTools 以进行可视化。这按预期工作:
public class MonitoringEventsODataV3Controller : EntitySetController<MonitoringEvent, string>
{
private readonly IEventMonitorCache _eventMonitorCache;
public MonitoringEventsODataV3Controller([NotNull]IEventMonitorCache eventMonitorCache)
{
_eventMonitorCache = eventMonitorCache;
}
[ODataRoute("MonitoringEvents")]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public override IQueryable<MonitoringEvent> Get()
{
var allEvents = _eventMonitorCache.GetAll();
return allEvents.AsQueryable();
}
}
但我正在努力解决的是 Excel PowerQuery 所做的 OData 过滤。我知道我还没有进行任何服务器端过滤,但这并不重要。当我过滤任何属性并单击刷新时,PowerQuery 会同时发送多个请求(我看到最多三个)。我相信它首先获取整个数据集,然后使用过滤器执行以下请求。这会导致 ServiceStack.Redis 出现各种异常:
An exception of type 'ServiceStack.Redis.RedisResponseException' occurred in ServiceStack.Redis.dll but was not handled in user code
附加信息,如:
Additional information: Unknown reply on multi-request: 117246333|company|osdmonitoringpreinst|2014-12-22|113917, sPort: 54980, LastCommand:
或者
Additional information: Invalid termination, sPort: 54980, LastCommand:
或者
Additional information: Unknown reply on multi-request: 57, sPort: 54980, LastCommand:
或者
Additional information: Type definitions should start with a '{', expecting serialized type 'CachedMonitoringEvent', got string starting with: u259447|company|osdmonitoringpreinst|2014-12-18|1
所有这些异常都发生在_eventsCache.GetAll()
.
一定有什么我错过了。我确信 Redis 能够在同一个集合上“同时”处理大量请求,但显然我做错了。:)
顺便说一句:Redis 2.8.12 正在 Windows Server 2008 机器上运行(很快 2012 年)。
感谢您的任何建议!