我把多個應用程序實例的問題上後面燃燒器。不是沒關係,但是如果你是針對接口進行編程,那麼在某些時候你可以用緩存的東西替換你的實現。
如果您希望平均請求時間超過五分鐘的持續時間,那麼您需要一個彈出過期條目的列表。下面是在一個刺:
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's singleton lifestyle)。我不喜歡創建單例。我寧願創建一個「普通」類,然後管理它以保持單個實例。像溫莎這樣的DI容器可以很容易地實現。
我認爲在這樣的實現中一個重要的因素是保持雜亂的切換邏輯分離 - 隱藏在某種工廠中,而不是使用if/then
所有邏輯來檢查平均響應時間並調用任一API在一個大班上。
舉例來說,如果你有代表呼籲得到的數據,像IMyDataProvider
的接口,那麼你可以這樣定義
interface IMyDataProviderFactory
{
IMyDataProvider Create();
}
你的類只取決於該工廠接口的工廠。執行IMyDataProviderFactory
的類將檢查您的平均響應時間,並返回調用外部API的IMyDataProvider
的實現或使用您的計算的實現。
這樣,該邏輯的複雜性就與依賴於API的任何類保持獨立。
溫莎與那些abstract factories也很好。其他DI容器也使它們變得簡單,並且這種功能被內置到ASP.NET Core中。你並沒有問及依賴注入,但我建議研究它。它可以更輕鬆地管理這種複雜性並保持可維護性。
回到多個應用程序實例和分佈式緩存 - 您可以看到工廠模式實現如何更容易管理。假設今天這是一個例子,但明天你想通過分佈式緩存共享這些數據。你在哪裏做這個改變?大多數依賴於此API的代碼根本不需要更改,因爲它不會「知道」任何這些實現細節。您可以更改存儲每個API調用時間的代碼,並更改工廠的實施。
如果你有自己的實現,那麼爲什麼你需要打電話給第三方?或者在幾小時後致電第三方並將數據存儲在某處,以便更快地獲得數據。 –
數據在第三方「實時」更新,所以我想每次都調用它,除非它在最後幾分鐘內變得接近無響應。 – mitomed