2017-05-02 109 views
0

在.Net應用程序中使用C#時,我必須進行昂貴的調用才能獲取某些數據給第三方API,並且依賴於此API有時候會更慢喜歡。通過不同的請求跟蹤.net應用程序變量

事情是這樣的,數據將是準確的,但我可以自己計算精度較低。所以我在考慮如何能夠讓我們跟蹤最近5分鐘內的平均請求時間,以及如果它大於我使用我自己的實現的閾值更改。

方法的草圖會是這樣的:

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

即使我非常希望能夠換一個接口的第三方,該礦將實現並改變它在運行時,它會很高興有。

但主要問題是如何將這個狀態保存在內存中。我只能想到使用靜態類,我已經閱讀了有關ApplicationState的內容,但不確定這些是否是最好的方法。

此外,不是我的小項目,但如何解決這些解決方案?如果我不得不考慮運行我的應用程序的幾個實例,我認爲唯一的解決方案是使用外部存儲(redis或類似?)並在檢查時查詢它。

很抱歉,如果這個問題是太一般,但認爲這是解決一個有趣的問題,不知道究竟如何最好地接近它

感謝

+1

如果你有自己的實現,那麼爲什麼你需要打電話給第三方?或者在幾小時後致電第三方並將數據存儲在某處,以便更快地獲得數據。 –

+0

數據在第三方「實時」更新,所以我想每次都調用它,除非它在最後幾分鐘內變得接近無響應。 – mitomed

回答

1

我把多個應用程序實例的問題上後面燃燒器。不是沒關係,但是如果你是針對接口進行編程,那麼在某些時候你可以用緩存的東西替換你的實現。

如果您希望平均請求時間超過五分鐘的持續時間,那麼您需要一個彈出過期條目的列表。下面是在一個刺:

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調用時間的代碼,並更改工廠的實施。