Gitstar ranking là một trang web thú vị để thống kê các trang được đánh giá sao nhiều nhất trên Github. Nhiệm vụ trong bài này là dựng một crawler có thể thu thập được thông tin các bản release của 5000 repository nhiều sao nhất Github.
git clone <your-repo-url>
cd <ten-thu-muc-repo>cd <1 trong 4 foler>Trong thư mục thực nghiệm thường có một thư mục setup-data hoặc mục tên khác nhưng có docker-compose file là được
cd setup-data
docker-compose upSau khi xong, quay lại thư mục thực nghiệm:
cd ..
go run cmd/main.goLệnh trên sẽ khởi chạy server tại localhost:<port>.
Sau khi server khởi động, bạn có thể gọi các API như sau:
GET /api/repos/crawl: crawl toàn bộ repositoriesGET /api/repos/{repoID}: lấy thông tin một repository
GET /api/releases/crawl: crawl toàn bộ releasesGET /api/releases/{releaseID}: lấy thông tin một releaseGET /api/releases/{releaseID}/commits: crawl commit theo release
GET /api/commits/crawl: crawl toàn bộ commitsGET /api/commits/{commitID}: lấy thông tin một commit
- Log hệ thống được lưu tại thư mục
logstrong từng thực nghiệm.
- Go (Golang): ngôn ngữ lập trình chính để xây dựng server và các thành phần logic
- Colly: thư viện crawler mạnh mẽ cho Go
- Chi Router: router HTTP nhẹ và nhanh
- Logrus: logging framework
- Viper: quản lý cấu hình ứng dụng
- GORM: ORM tương tác với cơ sở dữ liệu
- Docker Compose: phục vụ việc khởi tạo cơ sở dữ liệu dễ dàng qua
setup-data
- Queue-Based Load Leveling: dữ liệu được đưa vào hàng đợi (queue) thay vì ghi trực tiếp vào DB, giúp tăng tốc độ crawl và giảm tải cho DB
- Circuit Breaker Pattern
| Repos | Releases | Commits | |||||||
|---|---|---|---|---|---|---|---|---|---|
| crawled | time (s) | %error | crawled | time (s) | %error | crawled | time (s) | %error | |
| Baseline | 5000 | 17.783 | 0% | 1890 | 1h53 | 0% | _ | _ | 0% |
| Exp 1 | 5000 | 5.3 | 0% | 45837 | 15p34 | 0% | 36822 | 13p56 | 0% |
| Exp 2 | 5000 | 4.3 | 0% | 25690 | 8p28 | 0% | 37682 | 12p55 | 0% |
| Exp 3 | 5000 | 6.5 | 0% | 9835 | 6p28 | 0% | 6570 | 4p14 | 0% |
Baseline là một crawler siêu đơn giản, chỉ có thể cào dữ liệu đơn thuần tự động, mà chưa có bất kỳ xử lý giúp tối ưu về mặt thời gian và lượng dữ liệu crawled được.
Các vấn đề baseline này gặp phải:
- Database gặp quá nhiều truy vấn ghi -> nghẽn
- Tốc độ crawl dữ liệu về rất chậm do qúa nhiều truy vấn ghi mà mỗi lần chỉ ghi vào được có 1 record của dữ liệu
- Data crawled về không được nhiều do nghẽn tắc xảy ra
Các nguyên nhân dẫn đến những vấn đề trên:
- Thao tác ghi vào database chưa tối ưu
- Chưa sử dụng các cơ chế giúp crawl nhiều luồng dữ liệu cùng lúc
Crawl đa luồng (thực nghiệm 4 - 10 luồng), đồng thời sử dụng batch để cho phép ghi batch 100 records cùng 1 lúc. => Các cải tiến:
-
Tận dụng đỗ trễ mạng
- Tạo nhiều đồng thời, tận dụng tối đa độ trễ mạng từ đó rút ngắn thời gian crawl
-
Ổn định hơn so với 1 luồng đơn
- Nếu một luồng bị block (timeout, delay), các luồng khác vẫn tiếp tục hoạt động, ngăn tình trạng “điểm chết” toàn bộ quá trình crawl so với việc chỉ sử dụng mỗi 1 luồng như baseline.
-
Giảm số lượng truy vấn DB nhờ batch insert
- Gom 100 kết quả crawl vào một lô (batch) trước khi một thao tác ghi
- Sử dụng transaction đảm bảo tính nhất quán của dữ liệu trong quá trình crawl và insert lượng lớn data từ crawler
-
Tăng tốc độ ghi & giảm latency tail
- Ghi 100 bản ghi cùng lúc tận dụng tốt I/O throughput.
- Giảm thời gian chờ đợi cho mỗi batch dữ liệu, giúp crawler không phải chờ quá lâu giữa các batch.
Crawl dùng queue, các data crawl cào về được nhét vào queue để đợi khi nào database rảnh thì sẽ thực hiện ghi vào db, đồng thời cũng áp dụng cơ chế batch-insert như pipeline 1 => Các cải tiến đạt được:
-
Tăng throughput cho crawler
- Crawler chỉ cần đẩy kết quả vào queue mà không phải chờ ghi xong vào DB => Giảm thời gian chờ, việc crawl được thực hiện liên tục từ đó giảm thời gian crawl xuống
-
Điều tiết tải (Back‑pressure)
- Queue lưu trữ lượng data chờ ghi. Khi DB bận, consumer giảm tốc độ ghi tự động, crawler vẫn tiếp tục (đến ngưỡng queue).
-
Giảm số lượng truy vấn DB nhờ batch insert và tăng tốc độ ghi (Lý do tương tự exp 1 vì sử dụng batch-inserted)
Áp dụng Circuit Breaker => Các cải tiến:
-
Tránh sự cố
- Trong trường server đích liên tục response lỗi, cơ chế Circuit Breaker sẽ bảo vệ các API không bị gọi liên tục => Crawler không bị sập hoàn toàn
- Sau một khoảng thời gian thì crawler có thể tự phục hồi được nhờ cơ chế half-open của Circuit Breaker
-
Tăng độ ổn định và hiệu suất của hệ thống
- Circuit Breaker luôn giữ cho 3 API không bị sập (như trên đã giải thích)
- Crawler bỏ qua những request lỗi => Tiết kiệm thời gian crawl
-
Giảm số lượng truy vấn DB nhờ batch insert và tăng tốc độ ghi (Lý do tương tự exp 1 vì sử dụng batch-inserted)