2012-04-16 24 views
12

Chúng tôi đang đối mặt với nhiệm vụ chuyển đổi dịch vụ REST dựa trên mã tùy chỉnh thành API Web. Dịch vụ này có số lượng yêu cầu đáng kể và hoạt động trên dữ liệu có thể mất chút thời gian để tải, nhưng khi tải nó có thể được lưu trữ và sử dụng để phục vụ tất cả các yêu cầu gửi đến. Phiên bản trước của dịch vụ sẽ có một luồng chịu trách nhiệm tải dữ liệu và đưa nó vào bộ nhớ cache. Để ngăn chặn IIS chạy ra khỏi các trình khách công việc chủ đề sẽ nhận được phản hồi "quay lại sau" cho đến khi bộ nhớ cache sẵn sàng.Đồng thời và khả năng mở rộng API Web

Sự hiểu biết của tôi về API Web là nó có hành vi không đồng bộ được tích hợp bằng thao tác trên nhiệm vụ và kết quả là số lượng yêu cầu sẽ không liên quan trực tiếp đến số lượng chuỗi vật lý được giữ.

Trong triển khai mới của dịch vụ, tôi dự định để cho các yêu cầu đợi cho đến khi bộ nhớ cache sẵn sàng và sau đó thực hiện trả lời hợp lệ. Tôi đã thực hiện một bản phác thảo rất thô của mã để minh họa:

public class ContactsController : ApiController 
{ 
    private readonly IContactRepository _contactRepository; 

    public ContactsController(IContactRepository contactRepository) 
    { 
     if (contactRepository == null) 
      throw new ArgumentNullException("contactRepository"); 
     _contactRepository = contactRepository; 
    } 

    public IEnumerable<Contact> Get() 
    { 
     return _contactRepository.Get(); 
    } 
} 

public class ContactRepository : IContactRepository 
{ 
    private readonly Lazy<IEnumerable<Contact>> _contactsLazy; 

    public ContactRepository() 
    { 
     _contactsLazy = new Lazy<IEnumerable<Contact>>(LoadFromDatabase, 
      LazyThreadSafetyMode.ExecutionAndPublication); 
    } 

    public IEnumerable<Contact> Get() 
    { 
     return _contactsLazy.Value; 
    } 

    private IEnumerable<Contact> LoadFromDatabase() 
    { 
     // This method could be take a long time to execute. 
     throw new NotImplementedException(); 
    } 
} 

Xin đừng đặt quá nhiều giá trị trong việc thiết kế mã - nó chỉ được xây dựng để minh họa cho vấn đề và không phải là cách chúng tôi đã làm nó trong giải pháp thực tế. IContactRepository được đăng ký trong container IoC như là một singleton và được tiêm vào bộ điều khiển. Lazy với LazyThreadSafetyMode.ExecutionAndPublication đảm bảo chỉ thread/request đầu tiên đang chạy mã khởi tạo, các rquests sau bị chặn cho đến khi khởi tạo hoàn tất.

API Web có thể xử lý 1000 yêu cầu đang chờ khởi tạo để hoàn tất trong khi các yêu cầu khác không đánh Lazy này đang hoạt động và không có IIS chạy ra khỏi chuỗi công việc không?

Trả lời

10

Trả lại Task<T> từ hành động sẽ cho phép mã chạy trên luồng nền (ThreadPool) và giải phóng chuỗi IIS. Vì vậy, trong trường hợp này, tôi sẽ thay đổi

public IEnumerable<Contact> Get() 

để

public Task<IEnumerable<Contact>> Get() 

Hãy nhớ để trả lại một bắt đầu nhiệm vụ nếu không thì chủ đề sẽ chỉ ngồi và không làm gì cả.

Thực hiện lười biếng trong khi có thể hữu ích, ít có liên quan đến hành vi của API Web. Vì vậy, tôi sẽ không bình luận về điều đó. Có hoặc không có lười biếng, dựa trên nhiệm vụ trả về loại là con đường để đi cho các hoạt động chạy dài.

Tôi có hai bài đăng trên blog có thể hữu ích đối với bạn: herehere.