草庐IT

c# - ServiceStack Redis 同时读取请求的问题

coder 2023-11-08 原文

我正在使用 ServiceStack.Redis 实现来缓存通过 Web API 接口(interface)传送的事件。这些事件应该被插入到缓存中并在一段时间后(例如 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 年)。

感谢您的任何建议!

最佳答案

错误消息表明在多个线程中使用了 RedisClient 的非线程安全实例,因为它正在获取对它不期望/发送的请求的响应。

为了确保您正确使用,我只会传入线程安全的 IRedisClientsManager 单例,例如:

public EventMonitorCache([NotNull]IRedisClientsManager redisManager)
{
    this.redisManager = redisManager;
}

然后在你的方法中显式解析和释放 redis 客户端,例如:

public void AddOrUpdate(MonitoringEvent monitoringEvent)
{
    if (monitoringEvent == null)
        return;

    try
    {
        using (var redis = this.redisManager.GetClient())
        {
            var _eventsCache = redis.As<CachedMonitoringEvent>();
            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);
    }
}

在 GetAll() 中:

public List<MonitoringEvent> GetAll()
{
    using (var redis = this.redisManager.GetClient())
    {
        var _eventsCache = redis.As<CachedMonitoringEvent>();
        IList<CachedMonitoringEvent> allEvents = _eventsCache.GetAll();

        return allEvents
            .Where(e => e.MonitoringEvent != null)
            .Select(e => e.MonitoringEvent)
            .ToList();
    }
}

无论您的 EventMonitorCache 依赖项注册为什么生命周期,这都将起作用,例如由于 EventMonitorCache 不再保持 redis 服务器连接,因此作为单例保持是安全的。

关于c# - ServiceStack Redis 同时读取请求的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27857249/

有关c# - ServiceStack Redis 同时读取请求的问题的更多相关文章

  1. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  5. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  6. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  7. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  8. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. jquery - 我的 jquery AJAX POST 请求无需发送 Authenticity Token (Rails) - 2

    rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送

随机推荐