2013-05-30 33 views
26

Khi sử dụng tương lai trong scala, hành vi mặc định là sử dụng ngữ cảnh thực thi Implicits.global mặc định. Dường như điều này mặc định là làm cho một luồng có sẵn cho mỗi bộ xử lý. Trong một ứng dụng web luồng truyền thống hơn, điều này có vẻ giống như một mặc định kém khi tương lai đang thực hiện một nhiệm vụ như chờ đợi trên một cơ sở dữ liệu (trái ngược với một số nhiệm vụ ràng buộc CPU).Tôi có nên ghi đè lên ExecutionContext mặc định không?

Tôi hy vọng rằng việc ghi đè ngữ cảnh mặc định sẽ khá chuẩn trong sản xuất nhưng tôi có thể tìm thấy rất ít tài liệu về việc làm điều đó có vẻ như nó có thể không phổ biến. Tui bỏ lỡ điều gì vậy?

Trả lời

39

Thay vì nghĩ về nó như ghi đè bối cảnh thực thi mặc định, tại sao không hỏi thay vì "Tôi có nên sử dụng nhiều bối cảnh thực thi cho những thứ khác nhau không?" Nếu đó là câu hỏi, thì câu trả lời của tôi là có. Nơi tôi làm việc, chúng tôi sử dụng Akka. Trong ứng dụng của chúng tôi, chúng tôi sử dụng ngữ cảnh thực thi Akka mặc định cho chức năng không chặn. Sau đó, vì hiện tại không có trình điều khiển jdbc không chặn tốt, tất cả các cuộc gọi SQL chặn của chúng tôi đều sử dụng ngữ cảnh thực thi riêng biệt, trong đó chúng ta có một luồng cho mỗi phương thức kết nối. Giữ ngữ cảnh thực hiện chính (một ngã ba tham gia hồ bơi) miễn phí từ ngăn chặn dẫn đến một sự gia tăng đáng kể trong thông lượng cho chúng tôi.

Tôi nghĩ hoàn toàn ổn khi sử dụng nhiều ngữ cảnh thực thi khác nhau cho các loại công việc khác nhau trong hệ thống của bạn. Nó hoạt động tốt cho chúng tôi.

+3

+1 để đề cập đến yếu tố quyết định quan trọng là liệu bạn có sử dụng mã chặn (hoặc chạy dài) trong tương lai hay không. Nếu bạn không, sử dụng ngữ cảnh thực thi riêng biệt thực sự là phản tác dụng. –

+0

Nếu bạn muốn một trình điều khiển tùy chỉnh mà bạn có thể kiểm soát nhưng muốn gắn bó với tính song song mặc định và các tham số khác, có vẻ như 'ExecutionContext.fromExecutor (new scala.concurrent.forkjoin.ForkJoinPool)' (không có tham số) dường như làm ; tạo ra một hồ bơi của 8 trên i7 của tôi với 8 lõi (incl. hyperthreading), phù hợp với những gì 'ForkJoinPool.commonPool' chứa. –

+0

@cmbaxter bạn có bao bọc các cuộc gọi JDBC của bạn trong 'chặn {}' bên trong tương lai không? Là nó cần thiết nếu có một ExecutionContext tách ra? –

2

Có, tạo và sử dụng ngữ cảnh thực thi khác trong ứng dụng của bạn chắc chắn là một ý tưởng hay.

Ngữ cảnh thực thi sẽ môđun hóa mô hình đồng thời của bạn và cách ly các phần khác nhau của ứng dụng, để nếu có sự cố trong ứng dụng của bạn, các phần khác sẽ ít bị ảnh hưởng hơn. Để xem xét ví dụ của bạn, bạn sẽ có một bối cảnh thực hiện khác nhau cho các hoạt động cụ thể DB và một số khác để nói, xử lý các yêu cầu web.

Trong this presentation bởi Jonas Boner mẫu này được gọi là tạo "Vách ngăn" trong ứng dụng của bạn để có độ ổn định cao hơn & khả năng chịu lỗi.

Tôi phải thừa nhận rằng mình chưa nghe nhiều về việc sử dụng ngữ cảnh thực thi. Tuy nhiên, tôi thấy nguyên tắc này được áp dụng trong một số khuôn khổ. Ví dụ: Play sẽ sử dụng các ngữ cảnh thực thi khác nhau cho các loại công việc khác nhau và chúng khuyến khích bạn chia nhiệm vụ của mình thành các nhóm khác nhau nếu cần: Play Thread Pools

Phần mềm trung gian Akka cũng gợi ý chia ứng dụng của bạn thành các ngữ cảnh khác nhau ứng dụng của bạn. Họ sử dụng khái niệm Dispatcher là ngữ cảnh thực thi trên pin.

Ngoài ra, hầu hết các toán tử trong thư viện đồng thời scala đều yêu cầu ngữ cảnh thực thi. Điều này là do thiết kế để cung cấp cho bạn sự linh hoạt bạn cần khi mô đun hóa ứng dụng của bạn đồng thời-khôn ngoan.

+1

Mặc định 'ExecutionContext' trong Scala là nhóm ForkJoin gần đây nhất. Cho rằng, tuyên bố của bạn rằng bối cảnh thực hiện toàn cầu "là có cho công việc nhỏ, nhanh chóng nhưng nó chắc chắn sẽ không quy mô cho một ứng dụng lớn hơn" là vô căn cứ. –

+0

Nó không phải là bối cảnh thực thi mặc định không phải là thực hiện trong chính nó. Tôi có nghĩa là để nói rằng chỉ sử dụng một ngữ cảnh thực hiện trong một ứng dụng quy mô lớn không phải là điều tốt nhất. Tuy nhiên, tôi đã xóa nhận xét đó vì nó rất khó hiểu. –

3

Câu trả lời "đúng" là các phương pháp của bạn cần sử dụng ExecutionContext yêu cầu ExecutionContext trong chữ ký của chúng, vì vậy bạn có thể cung cấp ExecutionContext (s) từ "bên ngoài" để kiểm soát thực thi ở cấp cao hơn.

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