2015-12-28 14 views
9

Tôi hiện có API cho một trong các dự án của mình và dịch vụ chịu trách nhiệm tạo tệp xuất dưới dạng CSV, lưu trữ và lưu trữ chúng ở đâu đó trong đám mây.Trả lời với số lượng lớn các đối tượng thông qua API Rails

Vì API của tôi được viết bằng Rails và dịch vụ của tôi trong Ruby thuần túy, tôi sử dụng đá quý của cô trong dịch vụ để tương tác với API. Nhưng tôi thấy việc triển khai hiện tại của tôi kém hiệu quả hơn, vì tôi thực hiện dịch vụ Model.all trong dịch vụ của mình, do đó kích hoạt yêu cầu có thể chứa quá nhiều đối tượng trong phản hồi.

Tôi tò mò về cách cải thiện toàn bộ tác vụ này. Dưới đây là những gì tôi đã nghĩ đến:

  • thực hiện phân trang ở cấp API và gọi Model.where(page: xxx) từ dịch vụ của tôi;
  • tạo CSV thực tế ở cấp API và gửi CSV trở lại dịch vụ (điều này có thể được thực hiện đồng bộ hóa hoặc không đồng bộ).

Nếu tôi sử dụng cách tiếp cận đầu tiên, tôi cần truy xuất bao nhiêu đối tượng trên mỗi trang? Câu trả lời lớn đến mức nào?

Nếu tôi sử dụng phương pháp thứ hai, điều này sẽ mang lại chi phí cao hơn cho yêu cầu (và tôi đoán rằng các yêu cầu API sẽ không mất nhiều thời gian) và tôi tự hỏi liệu đó có phải là công việc của API để thực hiện điều này hay không.

Tôi nên làm theo phương pháp nào? Hoặc, có cái gì đó tốt hơn mà tôi đang thiếu?

Trả lời

3

Bạn cần truyền nhiều thông tin qua quy trình ruby, điều đó không hề đơn giản, tôi không nghĩ bạn đang thiếu gì ở đây.

Nếu bạn quyết định tạo CSV ở cấp API thì bạn sẽ nhận được gì khi duy trì dịch vụ? Bạn chỉ có thể bỏ dịch vụ hoàn toàn vì thay thế dịch vụ của bạn bằng proxy nginx sẽ làm điều tương tự tốt hơn (nếu bạn chỉ phát trực tiếp phản hồi từ máy chủ API)?

Nếu bạn quyết định phân trang, chắc chắn sẽ giảm hiệu suất, nhưng không ai có thể cho bạn biết chính xác số trang bạn nên phân trang - trang lớn hơn sẽ nhanh hơn và tiêu thụ nhiều bộ nhớ hơn (giảm thông lượng bằng cách có thể chạy ít công nhân hơn)), các trang nhỏ hơn sẽ chậm hơn và tiêu thụ ít bộ nhớ hơn nhưng cần nhiều công nhân hơn vì thời gian chờ IO,

số chính xác sẽ phụ thuộc vào thời gian phản hồi IO của ứng dụng API và đám mây và cơ sở hạ tầng của bạn. người ta có thể cung cấp cho bạn một câu trả lời đơn giản mà bạn có thể làm theo mà không cần thử nghiệm với một bài kiểm tra căng thẳng, và một khi bạn thiết lập một bài kiểm tra căng thẳng, bạn sẽ nhận được một số của riêng bạn - tốt hơn so với ước tính của bất kỳ ai.

Đề xuất, viết thêm một chút về vấn đề của bạn, những ràng buộc bạn đang làm việc dưới dạng v.v. và có thể ai đó có thể giúp bạn giải quyết triệt để hơn một chút. Vì lý do nào đó, tôi có cảm giác rằng những gì bạn đang tìm kiếm là bộ xử lý nền như sidekiq hoặc công việc bị trì hoãn hoặc có thể kết nối dịch vụ của bạn với DB trực tiếp thông qua chế độ xem DB nếu bạn đang lo lắng để tách ứng dụng của mình hoặc nginx proxy cho các phản hồi API, hoặc không có gì cả ... nhưng tôi thực sự không thể nói mà không có thêm thông tin.

+0

Cảm ơn bạn đã chia sẻ ý kiến ​​của mình! Tôi không muốn kết nối trực tiếp với DB từ dịch vụ vì mục đích cô lập; Sau đó tôi sẽ cần các mô hình ở nhiều nơi, và vì dịch vụ không phải là Rails, tôi sẽ có một thời gian khó khăn để làm điều này (đã trải qua điều này rồi). Tôi cũng không thể mương dịch vụ được; tính năng CSV này chỉ là một phần của dịch vụ. Về xử lý nền, bạn tham khảo điểm thứ hai của tôi, làm nó theo cách không đồng bộ? – linkyndy

+0

Về các ràng buộc, tôi chỉ tìm cách tách các thành phần; thế hệ CSV sẽ chỉ xảy ra một lần mỗi ngày và vì nó nằm trong một dịch vụ riêng biệt, tôi đoán nó sẽ không ảnh hưởng đến bất cứ thứ gì nếu chạy nhiều hơn một chút. – linkyndy

+0

Làm thế nào về việc tạo CSV trong ứng dụng API trong một công việc cron hoặc bộ xử lý nền và chỉ cần phục vụ nó bởi Dịch vụ khi được yêu cầu? – bbozo

3

Tôi nghĩ điều đó thực sự phụ thuộc vào cách bạn muốn xác định 'hiệu suất' và mục tiêu cho API của bạn là gì. Bạn có muốn đảm bảo rằng không có yêu cầu nào đối với API của bạn mất hơn 20msec để phản hồi, hơn là việc thêm phân trang sẽ là một cách tiếp cận hợp lý. Đặc biệt nếu thế hệ CSV chỉ là một trường hợp cạnh, và API thực sự được xây dựng cho các dịch vụ khác. Số lượng mục trên mỗi trang sau đó sẽ bị giới hạn bởi tốc độ mà tại đó bạn có thể phân phối chúng.Dịch vụ của bạn sẽ không đặc biệt hiệu quả hơn (thậm chí ít hơn), vì nó cần phải gọi dịch vụ nhiều lần.

Tạo cuộc gọi không đồng bộ (có thể với webhook dưới dạng gọi lại) sẽ đáng để thêm vào API của bạn nếu bạn cho rằng đó là trường hợp sử dụng hợp lệ cho các dịch vụ đổ toàn bộ tập hợp.

Có nói rằng, tôi nghĩ nghiêm túc nói rằng công việc của API là nhanh chóng và đáp ứng. Vì vậy, có thể cố gắng tìm ra cách bộ nhớ đệm có thể cải thiện thời gian phản hồi, do đó, phân trang thông qua tất cả các bản ghi là hợp lý. Mặt khác, công việc của dịch vụ là chú ý đến số lượng cuộc gọi đến API, vì vậy có thể lưu trữ các bản ghi cũ cục bộ và chỉ thăm dò ý kiến ​​cập nhật thay vì bán toàn bộ các bản ghi mỗi lần.

+0

Cảm ơn bạn đã đăng bài. Thật vậy, thế hệ CSV là một trường hợp cạnh, thông thường dịch vụ sẽ không cần nhiều dữ liệu để nhận được từ API. Về giới hạn, kể từ khi tôi gửi các đối tượng serialized trở lại từ API, họ sẽ có một số byte trong kích thước, và tôi đã tự hỏi làm thế nào lớn (kích thước) một phản ứng có thể được. Về async và webhooks, vì đó là một hoạt động hiếm, tôi đoán tôi sẽ cho phép ứng dụng dịch vụ của tôi "chờ" cho đến khi API gửi mọi thứ; hoặc là async thực sự giá trị nó trong trường hợp này? Như một kết luận, bạn có bất kỳ cách tiếp cận khác trong tâm trí? Bởi vì tôi cảm thấy bạn đang nói một trong hai lựa chọn là không đủ tốt. – linkyndy

+0

Vâng, tôi đã ở trong tình huống đó tôi sẽ rất có thể cũng đi cho cách tiếp cận thực dụng và tạo CSV trên api-side có thể với một respond_to chặn. Kích thước không phải là một vấn đề, trừ khi chúng ta nói về vài chục megabyte. Sau đó, mức tiêu thụ bộ nhớ có thể là một vấn đề. Các kết nối Ruby Socket có thời gian chờ phản hồi mặc định, tôi tin rằng có thể xảy ra ngay cả trước giới hạn kích thước. – skahlert

+0

Truyền trực tuyến phản hồi có thể là cách hay để giảm tác động lên bộ nhớ và cơ sở dữ liệu. [This] (http://smsohan.com/blog/2013/05/09/genereating-and-streaming-potentially-large-csv-files-using-ruby-on-rails/) có thể hữu ích. – skahlert

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