通过不同的请求跟踪.NET应用程序变量



在.NET应用程序中使用C#时,我必须进行昂贵的调用才能将一些数据获取到第三方API,并且取决于这一点,有时我想要的是较慢。<<<<<<<<<<<<<<<</p>

的事情是,数据将是准确的,但我可以自己精确地计算出来。因此,我在想我如何能够跟踪过去5分钟内的平均请求时间,并且如果使用我自己的实现大于我的门槛更改。

该方法的草图将是这样的:

    public int GetMyData()
    {
        return isTooSlow() ? _ownImplementation.GetData() : thirdParty.GetData();
    }

即使理想情况下,我也希望能够将第三方包裹在我的界面中,并在运行时更改它,这将是一个不错的选择。

,但是主测量将是如何将该状态保持在内存中。我只能想到使用静态类,我已经阅读了有关应用程序的有关方法,但不确定是否是最好的方法。

此外,不是我的小型项目,而是这些解决方案中的任何一个如何扩展?如果我不得不考虑应用程序运行的几个实例,我认为唯一的解决方案是使用外部存储(Redis或Chike?(并在进行检查时查询它。

对不起,如果问题太通用,但认为解决方案是一个有趣的问题,并且不知道如何最佳地处理它

谢谢

我会将多个应用程序实例的问题放在背面燃烧器上。并不是没关系,但是如果您正在针对接口进行编程,那么在某个时候,您可以用缓存的东西替换实现。

如果您需要在五分钟之类的持续时间内平均请求时间,则需要弹出过期条目的列表。这是一个刺伤:

internal class TimestampedEntry<T>
{
    internal DateTimeOffset Timestamp { get; private set; }
    internal T Value { get; private set; }
    internal TimestampedEntry(T value)
    {
        Timestamp = DateTimeOffset.Now;
        Value = value;
    }
}
public class ExpiringList<T> 
{
    private readonly List<TimestampedEntry<T>> _list = new List<TimestampedEntry<T>>();
    private readonly TimeSpan _expiration;
    public ExpiringList(TimeSpan expiration)
    {
        _expiration = expiration;
    }
    public void Add(T item)
    {
        lock (_list)
        {
          _list.Add(new TimestampedEntry<T>(item));              
        }
    }
    public IReadOnlyCollection<T> Read()
    {
        var cutoff = DateTimeOffset.Now - _expiration;
        TimestampedEntry<T>[] result;
        lock (_list)
        {
            result = _list.Where(item => item.Timestamp > cutoff).ToArray();
            _list.Clear();
            _list.AddRange(result);
        }
        return new ReadOnlyCollection<T>(result.Select(item => item.Value).ToList());
    }
}

确保您从列表中阅读时,它仅返回指定间隔内存储的项目,并删除其余的项目。您可以创建一个ExpiringList<TimeSpan>,为每个呼叫添加经过的时间,然后根据需要检查平均值。

在哪里存储它?我将其放在一个带有一个实例的课堂上。那可能是单身人士或静态课程。我更喜欢使用依赖性注入容器,该容器返回一个实例(例如Windsor的Singleton Lifestyle。(我不喜欢创建单例。我宁愿创建一个"正常"类,然后将其管理以保留一个实例。像温莎这样的di容器使它变得容易。

我认为这样的实现的一个重要因素是将凌乱的切换逻辑分开 - 隐藏在某种工厂中,而不是将所有逻辑具有if/then来检查平均响应时间,并将任何一个API调用一个大班级。

例如,如果您有一个界面代表呼叫获取数据(例如IMyDataProvider(,则可以定义像

这样的工厂
interface IMyDataProviderFactory
{
    IMyDataProvider Create();
}

您的课程仅取决于该工厂界面。实现IMyDataProviderFactory的类可检查您的平均响应时间,并返回调用外部API的IMyDataProvider的实现或使用您计算的实现。

这样,该逻辑的复杂性与任何依赖API的类别分开。

温莎也对那些抽象的工厂也很好。其他DI容器也使其容易,并且这种功能内置在ASP.NET核心中。您不是询问依赖注入,但我建议您研究它。它使管理这种复杂性并保持可维护变得更容易。


回到多个应用程序实例和分布式缓存 - 您可以看到工厂模式实现如何使其更易于管理。假设这是一个实例,但是明天您想通过分布式缓存共享此数据。您在哪里进行更改?大多数取决于此API的代码根本不需要更改,因为它不知道这些实现细节。您将更改存储每个API调用时间的代码,并更改工厂的实现。

最新更新