2010-07-20 15 views
9

Tôi gặp sự cố khi nhận 2 ứng dụng ASP.NET MVC giống hệt nhau để chia sẻ cùng một Phiên sử dụng Session StateServer. Lý do tôi đang cố gắng làm điều này là cuối cùng chúng tôi sẽ triển khai ứng dụng này trên 3 máy chủ web cần chia sẻ cùng một trạng thái. Chúng ta cần sử dụng StateServer vì chúng ta đang cố gắng giảm thiểu việc sử dụng db để lưu trữ không liên quan đến dữ liệu.Tại sao tôi không thể chia sẻ trạng thái Phiên giữa 2 ứng dụng web với StateServer? Tôi đang thiếu gì?

Setup:

tôi đã triển khai các cơ sở mã cùng http://localhost/App1http://localhost/App2

cả hai đều có file Web.Config giống hệt với những điều sau:

<system.web> 
<sessionState mode="StateServer" 
       cookieless="false" 
       timeout="20" 
       stateConnectionString="tcpip=127.0.0.1:42424" /> 
       //stateConnectionString="tcpip=192.168.1.52:42424" /> // also doesn't work 
<machineKey 
    validationKey="8B9F68D0CC730F6F046D0173021C34B1A0D9A01C21D8E4D4A7A1DFF38332DEE8CBBAFEA503C18776614EE9D4F7EEA7E5D2D5571630547D822485A27B1EF53AC1" 
    decryptionKey="60009563EFCFC594FD1BC46684943AA398EE70412A624B2EB488BBB071F15ECF" 
    validation="SHA1" decryption="AES" /> 

Tôi đã sử dụng this tool to generate these machine keys

Các thử nghiệm:

tôi đặt sau đây vào một trong những điều khiển của tôi để kiểm tra xem nó đã làm việc:

ViewData["mode"] = requestContext.HttpContext.Session.Mode.ToString(); 

string timestamp = DateTime.Now.ToString(); 
if (requestContext.HttpContext.Session["timestamp"] == null) 
{ 
    requestContext.HttpContext.Session["timestamp"] = timestamp; 
} 

ViewData["timestamp"] = requestContext.HttpContext.Session["timestamp"].ToString(); 
ViewData["realtime"] = timestamp; 

với điều này trong giao diện:

<p> 
    Mode: <%= ViewData["mode"].ToString() %> 
</p> 
<p> 
    Time: <%= ViewData["timestamp"].ToString() %> 
</p> 
<p> 
    real time: <%= ViewData["realtime"].ToString() %> 
</p> 

Kết quả:

Đối với cả hai triển khai, khi trang đầu tiên tải, tôi có thể thấy rằng chế độ là StateServer và dấu thời gian được đặt cùng lúc với giá trị thời gian thực .. Tuy nhiên, nếu điều này đang hoạt động, chỉ trang đầu tiên phải có cùng một thời gian làm giá trị thời gian thực. Tải trang thứ hai nên đọc từ máy chủ StateServer vì giá trị dấu thời gian đó không còn null và hiển thị giá trị thời gian đó. Nhưng thay vào đó, nó hiển thị giá trị thời gian thực một lần nữa.

Khi tôi làm mới trang, tôi dấu thời gian vẫn giữ nguyên và giá trị thời gian thực luôn cập nhật. Điều này cho biết dấu thời gian đang được lưu vào Phiên, nhưng giá trị dấu thời gian luôn khác nhau cho cả hai lần triển khai khi nó giống nhau, vì vậy điều này cho biết Phiên không được chia sẻ.

Ai đó có thể chỉ ra nếu tôi đang làm điều gì đó sai hoặc nếu có điều gì khác tôi cần phải làm để có được điều này để làm việc? Cảm ơn

+0

bạn đã có thể hoàn thành này? –

+0

@DaveDev tôi biết tôi đến trễ bữa tiệc: P, nhưng điều này có thể giúp người khác. nếu bạn có thể tìm cách chia sẻ cùng một miền cho cookie phiên (xem https://msdn.microsoft.com/en-IN/library/ms228262(v=vs.85).aspx) và lưu trữ phiên làm việc tại dịch vụ phổ biến (DB/Redis) sau đó bạn hoàn toàn có thể chia sẻ phiên giữa nhiều máy chủ –

Trả lời

10

Không thể chia sẻ phiên mặc định giữa các ứng dụng khác nhau. Từ những gì tôi có thể thấy bạn có hai ứng dụng riêng biệt App1App2 chạy trong các thư mục ảo riêng biệt và thậm chí có thể là các hồ bơi ứng dụng riêng biệt, vì vậy đừng mong muốn chia sẻ phiên giữa chúng.

Như thường lệ, có workarounds mà bạn có thể thấy hữu ích. Như bạn có thể thấy nó sử dụng một hack (phản ánh) để phá vỡ quyết tâm của nhà thiết kế ASP.NET để không vạch trần các lớp và thuộc tính nhất định và làm cho cuộc sống của chúng ta trở thành những người phát triển khó khăn.

+0

Bạn nói đúng rằng chúng là các ứng dụng riêng biệt. Một tồn tại trong D: \ App1 và cái kia nằm trong D: \ App2, và nằm trong các thư mục ảo khác nhau trong DefaultWebSite trong IIS. Tuy nhiên, cả hai đều nằm trong DefaultAppPool. Lý do cho điều này là cuối cùng chúng tôi sẽ triển khai ứng dụng này trên 3 máy chủ web cần chia sẻ cùng một trạng thái. – DaveDev

+0

Tôi nghĩ rằng đó là thư mục ảo xác định tên ứng dụng và không phải là hồ bơi ứng dụng, vì vậy tôi đoán bạn sẽ phải sử dụng để hack mà buộc tên ứng dụng tương tự. –

+0

Ok, tôi sẽ xem xét điều này. Nếu chúng ta kết thúc lộ trình hack để đạt được kết quả này, tôi nghĩ rằng chúng ta có thể tốt hơn để gắn bó với cơ sở dữ liệu để lưu trữ phiên. Cách tiếp cận db dường như mạnh mẽ hơn. – DaveDev

2

Cập nhật: Đây là một bài trước tôi đã trả lời trên cùng một chủ đề này Sharing sessions across applications using the ASP.NET Session State Service

Như đã chỉ ra, dữ liệu Session được scoped vào ứng dụng. Đó là ứng dụng bạn tạo trong IIS.Vì vậy, hai ứng dụng có cùng id phiên sẽ không chia sẻ cùng một phiên vì phạm vi ứng dụng.

Là một ý tưởng thay thế có thể hoặc có thể không khả thi đối với bạn. Bạn có thể tạo một ứng dụng gốc và có mã cho D: \ App1 và D: \ App2 trong hai thư mục con.

d:\Root 
    web.config 
    \App1 
    default.aspx 
    ... 
    \App2 
    default.aspx 
    ... 

Sau đó, trong IIS, bạn tạo Ứng dụng trỏ tới d: \ Root. Bạn cũng có thể tạo một ứng dụng trong IIS và sau đó theo ứng dụng bạn tạo hai thư mục ảo, một trỏ đến D: \ App1 và một để D: \ App2, sau đó họ cũng có thể chia sẻ một đơn web.config tại ứng dụng cấp độ. Điều quan trọng là hai thư mục ảo chỉ là ảo và không được tạo dưới dạng Ứng dụng.

Vì vậy, bạn bố trí ổ cứng có thể trông như thế này

D:\Root 
    web.config 

D:\App1 
    default.aspx 
    ... 

D:\App2 
    default.aspx 
    ... 

Tạo ứng dụng gốc trỏ đến D: \ Root và sau đó dưới sự ứng dụng tạo hai thư mục ảo App1 trỏ đến D: \ App1 và App2 trỏ tới D: \ App2.

Hiệu ứng trong cả hai trường hợp là bạn thực sự có một ứng dụng được chia thành hai phần, cả trong cùng một phạm vi phiên do đó mã cho cả hai có thể chia sẻ cùng một dữ liệu phiên.

2

Bạn cũng phải đảm bảo rằng đường dẫn ứng dụng cho ứng dụng phải giống nhau trên cả hai máy chủ web. Có một bài báo cũ ở đây có thể giúp

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q325056

Chúng tôi hiện đang gặp một vấn đề tương tự, ngoại trừ việc chúng tôi đang sử dụng IIS 7.5 và các đường dẫn ứng dụng được ẩn cho chúng tôi (không sử dụng metabase nữa). Có ai biết một cách xử lý sự cố này với IIS 7.5?

+0

Theo quan điểm của tôi, tôi nghĩ Microsoft đã bỏ bóng bằng IIS trong một vài phiên bản trước. – DaveDev

5

Thực ra bạn có thể chia sẻ phiên sử dụng chế độ máy chủ Sql.

Hãy thử điều này: -

tôi chỉ cần thay đổi các thủ tục tức là

USE ASPState 
GO 

ALTER PROCEDURE dbo.TempGetAppID 
    @appName tAppName, 
    @appId int OUTPUT 
AS 

    -- start change 

    -- Use the application name specified in the connection for the appname if specified 
    -- This allows us to share session between sites just by making sure they have the 
    -- the same application name in the connection string. 
    DECLARE @connStrAppName nvarchar(50) 
    SET @connStrAppName = APP_NAME() 

    -- .NET SQLClient Data Provider is the default application name for .NET apps 
    IF (@connStrAppName <> '.NET SQLClient Data Provider') 
     SET @appName = @connStrAppName 

    -- end change 

SET @appName = LOWER(@appName) 
SET @appId = NULL 

SELECT @appId = AppId 
FROM [ASPState].dbo.ASPStateTempApplications 
WHERE AppName = @appName 

IF @appId IS NULL BEGIN 
BEGIN TRAN 

SELECT @appId = AppId 
FROM [ASPState].dbo.ASPStateTempApplications WITH (TABLOCKX) 
WHERE AppName = @appName 

IF @appId IS NULL 
BEGIN 
EXEC GetHashCode @appName, @appId OUTPUT 

INSERT [ASPState].dbo.ASPStateTempApplications 
VALUES 
(@appId, @appName) 

IF @@ERROR = 2627 
BEGIN 
DECLARE @dupApp tAppName 

SELECT @dupApp = RTRIM(AppName) 
FROM [ASPState].dbo.ASPStateTempApplications 
WHERE AppId = @appId 

RAISERROR('SQL session state fatal error: hash-code collision between applications ''%s'' and ''%s''. Please rename the 1st application to resolve the problem.', 
18, 1, @appName, @dupApp) 
END 
END 

COMMIT 
END 

RETURN 0 
GO 

và sau đó sửa đổi web.config như: -

<sessionState mode="SQLServer" sqlConnectionString="Data Source=.;Integrated Security=True;Application Name=TEST" cookieless="false" timeout="20"></sessionState> 
    <httpRuntime targetFramework="4.5"/> 

Bạn phải thêm Tên ứng dụng và có giống nhau cho tất cả ứng dụng mà bạn muốn chia sẻ cùng một phiên.

Cảm ơn.

+0

điều này thực sự đã làm các trick :) –

+0

Không chỉ làm việc này, đó là thực hiện dễ nhất cho đến nay. Cảm ơn! –

+0

Đồng thời đảm bảo rằng các phím máy và ID ứng dụng của bạn giống nhau. https://blogs.msdn.microsoft.com/httpcontext/2012/06/22/shared-session-state-in-a-iis6-and-iis7-web-farm/ –

Các vấn đề liên quan