Xử lý import file Excel lớn với background job và websocket
White

Nguyễn Thế Huy viết ngày 26/11/2019

Xin chào mọi người, hôm nay trong bài viết này mình sẽ đề cập đến một cách đơn giản để xử lý import file excel lớn kết hợp giữa background job và websocket.

Bài toán

Import file excel lớn (hoặc cần thời gian xử lý lâu) lên hệ thống thường sẽ tốn nhiều thời gian trên 1 Http Request. Điều này gây ảnh hưởng không tốt đến trải nghiệm của người dùng, gây lag hệ thống, và có thể sẽ timeout (Điều gần như chắc chắn sẽ xảy ra). Ngoài ra nếu gặp vấn đề, việc retry lại là khá phức tạp.
Để khắc phục vấn đề trên, giải pháp thường thấy là sử dụng background job. Hệ thống nhận file xong sẽ đẩy vào queue xử lý. Ưu điểm là user sẽ không bị block thao tác hiện tại (do chạy bất đồng bộ). Tuy nhiên giải pháp này cũng bộc lộ một số nhược điểm, như user không biết được khi nào tiến trình kết thúc (sẽ phải thông báo sau); user cũng không nắm được tiến trình đã xử lý được bao nhiêu % (một UX quan trọng trong các tiến trình cần thời gian xử lý dài).

Hướng giải quyết

Các đoạn code trong ví dụ sau đây mình sử dụng laravel và laravel-websocket (giả lập giao thức Pusher) để làm websocket. Các bạn hoàn toàn có thể áp dụng các thư viện tương đương.
Cách giải quyết trong bài toán này sẽ là kết hợp giữa background job và websocket. Theo đó

  • Khi upload file lên, hệ thống lập tức đẩy vào job và kết thúc HTTP request

$request->file( 'file' )->move( public_path( 'files' ), $filename );
$filePath = public_path( 'files/' . $filename );
dispatch(new \App\Jobs\ImportExcel($filePath));

  • Job queue đếm số bản ghi, và emit về client thông qua một channel socket, ví dụ row-count
$import = new \App\Imports\ImportExcel();
Excel::import($import, $file);
$rows = $import->getRowCount();
$pusher = \PusherService::getClient();
$channelName = 'user-import';
$pusher->trigger( $channelName, 'row-count', $rows );
  • Ngay khi client nhận được message trên, hiện progress bar.
var channel = pusher.subscribe('user-import');
channel.bind('row-count', function (data) {
        if (!isNaN(data)) {
                $('#progress-bar').show();
                $('#progress-status').css({
                    width: '0%'
                });
            }
        });
  • Job queue tiến hành chạy từng bản ghi trong file excel và tiến hành handle, mỗi khi handle thành công hoặc thất bại sẽ tăng biến đếm bản ghi lên 1, đồng thời emit về client thông tin của bản ghi và row hiện thời đang chạy.
  • Client sẽ nhận được tiến trình (Tức số bản ghi đã xử lý thành công, trên tổng số bản ghi), đồng thời biết được trạng thái thành công hay thất bại của từng bản ghi đã xử lý.
  • Khi đã chạy đủ bản ghi, server emit message kết thúc, client đóng lại tiến trình upload và thông báo cho người dùng.

Hình mô tả đơn giản:
alt text

Ưu điểm của việc kết hợp này:

  • Tận dụng được background job, nhanh chóng giải phóng HTTP Request
  • User nắm được tiến trình upload và xử lý hoàn toàn theo thời gian thực
  • Khả năng retry là rất dễ dàng, user cũng hoàn toàn có thể thoát khỏi màn hình đang hoạt động rồi quay trở lại theo dõi tiến trình bất kỳ lúc nào => Tăng trải nghiệm người dùng.
  • Dữ liệu có thể được cache ở client nếu cần dùng tới

Với việc websocket đang được implement càng ngày càng đơn giản, mình nghĩ rằng bổ sung thêm websocket vào hệ thống sẽ không tốn quá nhiều thời gian phát triển cho các hệ thống đã có sẵn.

Cách làm này có thể áp dụng với hầu hết các tác vụ dài, nhưng tốn nhiều thời gian, và có thể quy ra các bước (step).

Cám ơn các bạn đã đọc, hy vọng bài viết có thể giúp ích một phần nào đó :D

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Nguyễn Thế Huy

10 bài viết.
60 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
32 8
Hi cả nhà, đây là bài viết đầu tiên của mình trên Kipalog nên có gì không hay mong các bạn thông cảm :D Realtime là gì ? Như chúng ta đều đã biế...
Nguyễn Thế Huy viết gần 3 năm trước
32 8
White
28 6
Xin chào mọi người :D Trong bài viết này mình sẽ trình bày một cách cơ bản để ứng dụng kỹ thuật Http Live Streaming (HLS) để play video trên web, ...
Nguyễn Thế Huy viết hơn 2 năm trước
28 6
White
25 6
Bài toán Machine Learning và những ứng dụng của nó đang ngày càng trở nên nổi bật trong những năm trở lại đây. Với sự phát triển thần tốc của cấu ...
Nguyễn Thế Huy viết hơn 1 năm trước
25 6
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
10 bài viết.
60 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!