4

StructureMap documentation on life cycle中,他們聲明一個範圍選項是HttpSession,並且它:「在HttpContext.Session集合中緩存實例,謹慎使用」。StructureMap在注入Session時警告注意事項 - 爲什麼?

我不知道該謹慎些什麼,而我的Google-fu正在讓我失望。

我們使用的用例是我們有一些昂貴的Web服務調用,我們想要緩存。其中一些是無國籍的,但其中一些與特定用戶有關。

我們什麼時候壞,頑皮的人,如果我們注入會話範圍?我們需要防範什麼?

回答

11

我會用一個極端的例子,緩存工作對象的單位(如LINQ to SQL的DataContext,實體框架的ObjectContextDbContext或NHibernate的ISession)描述了這樣的問題:

內存佔用

工作對象的單位通常會持有大量的對象。將會話對象放在HttpSession中意味着只要會話處於活動狀態,並且存在緩存中的所有對象,它就會一直存在。即使用戶在20分鐘後回來,您的應用程序也會承受這種內存壓力。這可能(並且在相當大的負載下)會導致內存不足異常。

數據變得陳舊

由於工作對象緩存的單元,它從數據庫中加載的所有實體,這些數據相當迅速變得陳舊。當數據被其他用戶更改時,默認情況下,緩存數據將不會被刷新,並且您可以在一個用戶看到一些數據,但另一個用戶看到其他數據時體驗到奇怪的行爲。由於您在會話的整個生命週期中緩存了數據,因此刷新頁面將不起作用。只有關閉瀏覽器才能工作(有時)。

系列化

當你縮放你的Web服務器了(這意味着你添加更多的服務器)的會話信息必須從一臺服務器傳送到另一個。您將不得不使用進程外高速緩存(例如MemCache或SQL Server)。工作單元對象很難或不可能序列化和反序列化,這意味着如果你想要或需要,你不能擴展。

摘要

的例子是極端的,因爲你永遠不應該在工作模式的單位使用每個會話的生活方式。但它仍然很清楚地描述了這個問題。每次會議的生活方式都會增加您的應用程序的內存佔用量,因爲服務保持很長時間。如果你使用這種服務來緩存數據,它可能會變得陳舊(儘管緩存可能只是你需要提高性能的東西)。雖然DTO通常很容易序列化,但這不適用於您註冊的任何服務。這意味着您不能擴展,因爲需要擴展可序列化的會話對象。

因此,不要在服務上使用Per Session生活方式,而是嘗試構建無狀態服務,以便它們可以註冊爲單例服務。他們需要的任何用戶特定數據都可以從HTTP會話中請求。

+1

這是一個恥辱的ASP。NET不會強制會話中的對象被序列化,即使存儲在進程中也是如此......這會導致Web項目以無法擴展的方式開始他們的生活,而不是從一開始就避免這種行爲。 –

+3

@MiguelAngelo:我同意。這就是爲什麼我總是將開發人員環境配置爲使用失步緩存,即使生產不這樣做。這會讓開發過程中出現問題。 – Steven