2011-08-01 24 views
8

Tôi sẽ tiếp tục và nói trước điều này bằng cách nói: Tôi có phần mới với WCF.Các vấn đề với mẫu đơn bên trong phương thức dịch vụ WCF

Tôi đang làm việc trên một quy trình phía máy chủ chịu trách nhiệm thực hiện rất nhiều logic nghiệp vụ. Nó có thể truy cập từ một khách hàng thông qua WCF.

Phương thức WCF chính của tôi yêu cầu một số phương thức riêng tư khác. Thay vì đi qua tất cả "dữ liệu tra cứu" tôi cần cho logic nghiệp vụ cho từng phương thức riêng, tôi quyết định sử dụng một cá thể đơn lẻ của một lớp có tên DataProvider chứa tất cả dữ liệu tra cứu này.

Khi kết thúc thường trình, tôi "giải phóng" dữ liệu tra cứu của DataProvider để lần tiếp theo quy trình được thực hiện, dữ liệu tra cứu mới nhất sẽ được sử dụng.

Vì vậy, đây là một ví dụ đơn giản:

public void Generate() 
{ 
     try 
     { 
      //populate singleton DataProvider with it's lookup data... 
      DataProvider.Instance.LoadLookupData(); 

      //do business logic... 
     } 
     finally 
     { 
      //release provider's lookup data... 
      DataProvider.Release(); 
     } 
} 

này hoạt động tuyệt vời cho đến khi tôi có hai khách hàng khác nhau mà thực hiện phương pháp này tại (hoặc gần) cùng một lúc. Vấn đề xảy ra bởi vì họ chia sẻ cùng một cá thể singleton và nhiệm vụ hoàn thành đầu tiên sẽ phát hành DataProvider trước khi hoàn thành khác.

Vì vậy, ...

Tùy chọn của tôi ở đây là gì?

Tôi muốn tránh đi qua tất cả dữ liệu tìm kiếm để mẫu đơn (hoặc một số dẫn xuất) có vẻ như là một lựa chọn tốt. Tôi cũng cần có khả năng hỗ trợ nhiều khách hàng gọi phương thức cùng một lúc.

Tôi tin rằng dịch vụ WCF được định cấu hình là "Mỗi cuộc gọi". Tôi không chắc chắn nếu có một cách để cấu hình một dịch vụ WCF để bộ nhớ tĩnh không được chia sẻ giữa các dịch vụ invocations.

Mọi trợ giúp sẽ được đánh giá cao.

+1

Ai đó sửa tôi nếu tôi sai ở đây, nhưng chuyển dữ liệu tra cứu vào một lớp khác sẽ không tạo bản sao hoàn toàn mới của tất cả dữ liệu của anh ấy, đúng không? Nó sẽ không chỉ là một bản sao của tham chiếu đến dữ liệu? (Trừ khi tất nhiên nó được serialized trên một ranh giới dịch vụ, mà không có khả năng âm thanh trong trường hợp này) –

+0

Tôi muốn hiểu những động lực cho việc có lớp singleton. Có phải thứ gì đó mà bạn chỉ tạo một lần và tất cả những người gọi đến dịch vụ của bạn cần phải có cùng một bản sao dữ liệu không? Hoặc là nó giống như một người gọi trở lại dịch vụ của bạn sẽ nhận được cùng một dữ liệu (phiên)? – Kangkan

+1

Lý do cho "singleton" là logic nghiệp vụ tạo ra khoảng 30 loại đối tượng khác nhau. Mỗi nhu cầu truy cập vào dữ liệu tra cứu. Có lẽ tôi đã lười biếng, nhưng tôi không cảm thấy muốn có cùng một lập luận với hơn 30 nhà xây dựng khác nhau. Lol. Tôi cảm thấy như singleton là cách tiếp cận sạch nhất để mỗi đối tượng có thể dễ dàng truy cập dữ liệu tra cứu. –

Trả lời

8

Theo mặc định WCF đang sử dụng "Per-Call", có nghĩa là phiên bản mới của dịch vụ WCF được tạo cho mỗi cuộc gọi của khách hàng. Bây giờ kể từ khi bạn thực hiện singleton mặc dù trường hợp mới của WCF được tạo ra nó vẫn gọi singleton của bạn.

Nếu bạn muốn tạo tra cứu được tạo cho mỗi cuộc gọi (như bạn hiện có), bạn không nên làm điều đó dưới dạng singleton. Bằng cách này, mỗi khách hàng gọi phương thức của bạn sẽ có phiên bản tra cứu mới, tôi nghĩ đó là ý định của bạn.

Tuy nhiên nếu bạn có tra cứu không thay đổi nhanh, tôi khuyên bạn nên chia sẻ nó giữa tất cả các cuộc gọi, điều này sẽ cải thiện hiệu suất của dịch vụ WCF của bạn. Bạn sẽ cần phải khai báo dịch vụ WCF của bạn như

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple 

Điều này không là tạo Singleton tự động cho bạn bằng cách WCF, vì vậy bạn không cần phải làm điều đó cho mình, thứ hai nó sẽ hỗ trợ> 1 người đồng thời (ConcurrencyMode.Multiple).

Bây giờ nếu bạn có tra cứu của bạn cũng được thay đổi và nó cần phải được nạp lại sau một khoảng thời gian, tôi vẫn sẽ khuyên bạn sử dụng

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple 

nhưng bên trong bộ nhớ cache mã của bạn nó và sau đó hết hiệu lực bộ nhớ cache của bạn tại thời gian cụ thể hoặc thời gian tương đối (1 giờ).

Dưới đây là một số liên kết có thể giúp bạn: 3 ways to do WCF instance management (Per call, Per session and Single)

Hy vọng điều này sẽ giúp.

+1

Tại sao bạn sử dụng chế độ instleton instancing nếu bạn đang sử dụng giải pháp lưu trữ được chia sẻ giữa các cuộc gọi? Có vẻ như sẽ đơn giản hơn khi sử dụng instancing cho mỗi cuộc gọi và giải pháp lưu trữ được chia sẻ, sau đó bạn không phải lo lắng (nhiều) về các mối quan tâm về an toàn luồng. –

+0

@Joel C Không quan trọng nếu bạn quyết định thực hiện nó cho mỗi cuộc gọi hoặc đơn, bạn vẫn cần phải suy nghĩ về đồng bộ hóa dữ liệu tải vào bộ đệm. Vì bộ nhớ cache sẽ là một cá thể duy nhất và bạn sẽ cần phải thực hiện đồng bộ hóa. Sử dụng Per-Call sẽ tạo một cá thể dịch vụ WCF mới cho mỗi máy khách và lưu trữ dữ liệu được lưu trữ phía sau. Bây giờ câu hỏi đặt ra là tại sao ví dụ WCF mới cần được tạo ra? Không có điểm cho nó, đó là lý do tại sao tôi đề nghị sử dụng Single. Kể từ ngày đọc từ bộ nhớ cache bạn không phải làm gì về đồng bộ hóa, nó là hoạt động chỉ đọc. –

+2

Tôi đã nói nhiều hơn về việc xử lý đồng bộ hóa trong các phương thức của dịch vụ WCF, kể từ 'ConcurrencyMode.Multiple' có nghĩa là có thể có nhiều luồng thực hiện cùng một phương thức cùng một lúc. Với mỗi cuộc gọi, bạn có một cá thể duy nhất cho mỗi yêu cầu, vì vậy việc đa luồng và đồng bộ hóa chỉ trở thành vấn đề khi bạn xử lý các biến tĩnh. –

1

đơn giản nhất là sử dụng một cơ chế đồng bộ - có bạn nhìn vào khóa (...) - điều này sẽ hoạt động như một gatekeeper rất giống một phần quan trọng (nếu bạn đã đi qua những người trong cửa sổ chương trình)

xác định một đối tượng tĩnh trong lớp học của bạn

tức

static object lockObject = new object(); 

và sử dụng nó trong Generate phương pháp

tức

void Generate() 
{ 
    lock(lockObject) 
    { 
    ... 
    } 
} 
+0

Tôi đã giả định rằng bạn đang tìm cách chia sẻ dữ liệu giữa các cuộc gọi - hoặc là mỗi callee tức là 2 người gọi nhận được dữ liệu khác nhau nhưng sẽ nhận được như vậy nếu cuộc gọi lại –

+0

Điều này chắc chắn sẽ hoạt động, nhưng logic nghiệp vụ mất vài phút . Chúng tôi không muốn chặn khách hàng bổ sung thực thi logic nếu một ứng dụng khách khác đang thực thi. –

4

Biến tĩnh trong dịch vụ WCF luôn được chia sẻ giữa các phiên bản bất kể WCF InstanceContextMode setting. Có vẻ như bạn nên sử dụng mẫu đệm để tra cứu dữ liệu. Các answers to this caching question cung cấp một số lựa chọn thay thế để lăn của riêng bạn mặc dù họ là một chút ngày. Ngoài ra, nếu bạn quyết định làm cho toàn bộ trường hợp dịch vụ là một đơn (InstanceContextMode = Single) là giải pháp dễ nhất, bạn nên biết rằng bạn thường sẽ hủy khả năng mở rộng dịch vụ trừ khi bạn cũng làm cho mã đa luồng (ConcurrencyMode=Multiple). Nếu bạn có thể gõ mã an toàn cho luồng trong giấc ngủ của bạn thì một dịch vụ đơn có thể dành cho bạn.

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