Hệ thống Viblo Code Challenge được xây dựng như thế nào

530
Hệ thống Viblo Code Challenge được xây dựng như thế nào

Chắc hẳn ai trong số chúng ta cũng đã từng tham gia 1 số cuộc thi về contest hay là code challenge. Ví dụ như TalenHubViblo CodeTop Coder …

Nhưng ít ai để ý đến xem những service đó được làm như thế nào? Làm thế nào có thể run được đoạn code mà mình đã submit?

Hôm nay mình sẽ đi đào sâu vào những hệ thống đó xem cụ thể nó được xây dựng như thế nào, và kiến trúc của nó ra sao. Đặc biệt để dễ hình dung thì mình sẽ đi lấy ví dụ về Viblo Code nhé.

Mình không phải là nhân viên của Framgia nên có thể hệ thống Viblo Code sẽ khác so với cái mà mình đã phỏng đoán. Nhưng mình nghĩ cơ chế nó sẽ giống nhau.

Mục đích bài viết:

  • Hiểu được các hệ thống về Code challenge làm việc như thế nào
  • Tự mình có thể xây dựng được 1 hệ thống như thế

Đối tượng hướng đến:

  • Người thích làm về mảng về hệ thống
  • Người có kinh nghiệm về Docker

Hệ thống Code Challenge là gì?

Code Challenge là dịch vụ dành cho lập trình viên rèn luyện kĩ năng về lập trình, cũng như các tư duy về giải thuật.

Như hình ảnh bên trên về Viblo Code chúng ta có thể thấy, nó bao gồm phần câu hỏi, phần viết code, phần chọn ngôn ngữ mà mình thích …

Ngoài ra còn có 1 số chức năng khác nữa như Ranking (code của ai chạy nhanh sẽ được xếp hạng cao hơn …), nhận thưởng nếu đứng top.

Yêu cầu về mặt chức năng

  • Với mỗi câu hỏi có thể chọn ngôn ngữ lập trình (shell, php, javascript, java …) mình muốn làm.
  • Khi submit code trả về kết quả, kèm theo thời gian thực thi
  • Có giới hạn về thời gian làm bài (ví dụ như chỉ làm trong 15p chẳng hạn)
  • Xếp hạng điểm của người dùng

Hôm nay mình sẽ tập trung chủ yếu vào phần thực thi code ứng với từng language (java, php, javascript …) . Còn phần ranking mình sẽ không đề cập đến ở đây.

Kiến trúc hệ thống

Mình nghĩ đầu tiên ai cũng sẽ đưa ra kiến trúc kiểu như này. Cùng xem xem nó có ổn không nhé.

Chúng ta có 1 con web server, và ở trong con web server này sẽ cài tất cả các package liên quan đến tất cả các ngôn ngữ để có thể chạy được. Ví dụ như sẽ cài php, nodejs, java, python … tất tần tật lên con web server này.

Và khi người dùng submit code của mình lên để test thì khi đó con web server này sẽ nhận request từ người dùng (giả sử như request này dạng json) bao gồm phần content và language.

Nó sẽ lưu cái phần content này vào 1 file. ví dụ như với ngôn ngữ php thì sẽ lưu file dạng main.php, nếu ngôn ngữ javascript thì sẽ lưu dạng main.js.

Và để xem đoạn code này có chạy được hay không thì web server sẽ chạy 1 đoạn code kiểu như này.

Khi đó nó sẽ trả về cho mình output của đoạn code và thời gian runtime cho người dùng. Với trường hợp là javascript hay python … thì cũng làm theo cách tương tự.

Vậy kiến trúc này có ổn không? Theo mình thì là không nhé. Có mấy lí do như sau:

  • Vì web server này chạy trực tiếp shell lên server của mình nên nếu như người dùng gửi 1 đoạn code kiểu như: rm -rf /var/www/html/* thì chắc ăn hành to rồi.
  • Vì cài nhiều package lên con web quá như thế cũng là nguyên nhân gây ra 1 số rủi ro về vấn đề bảo mật.

Để giải quyết bài toán trên thì chúng ta chỉ cần áp dụng docker vào là ok.

Cụ thể dưới đây là kiến trúc mình muốn đưa ra:

Đầu tiên Web Server nhận request và khởi chạy container tương ứng với language được gửi lên. Sau đó run code thông qua container đó và nhận kết quả trả về cho người dùng.

Vậy chúng ta đã quyết định được kiến trúc hệ thống hợp lý. Tiếp theo sẽ đi vào phần lập trình.

Thiết kế API

Về API thì mình nghĩ chỉ cần 1 cái API về submit code. Thông số đầu vào là content và language. Output sẽ trả về kết quả sau khi compile đoạn code của người dùng cùng với thời gian thực thi đoạn code.

Demo

  Cuộc thi sáng tạo phần mềm Angelhack Hanoi Hackathon 2016 và cơ hội vươn tới Thung Lũng Silicon

Để dễ hiểu thì mình sẽ làm 1 phần demo để các bạn dễ hình dung.

Đây là kết quả sau khi gọi API để submit code.

Còn đây là màn hình mô phỏng docker container làm việc (các bạn để ý cái màn hình terminal đằng sau đấy nhé). Cứ mỗi lần 1 request được gửi lên thì 1 container được khởi chạy và thực thi code. Nhìn khá là thú vị.

OK vậy các bạn cũng hiểu hiểu rõ cái API làm việc thế nào rồi đúng không. Bây giờ đi vào phần code nhé.

Về API mình sẽ code bằng Nodejs

Source code: https://github.com/nooptr/code-challenge

Về image để build cho từng language mình để ở trong thư mục docker.

  Hacker chỉ mất vài phút để tìm ra chìa khóa đầu tiên trong cuộc thi có giải thưởng 1 triệu USD Bitcoin

Ví dụ như với ngôn ngữ php thì nội dung của Dockerfile sẽ như sau:

Trong đó nội dung của file script.sh sẽ như sau:

Mục đích của file script.sh này là để thực thi compiler file code. Kết quả sau khi compiler sẽ được ghi vào file $output. Và thời gian thực thi sẽ được in ra màn hình.

Để web server có thể chạy được container thì cần phải cài đặt trước bằng lệnh:

Tiếp theo cùng đi xem API viết như nào nhé:

ếu ai code nodejs rồi thì mình nghĩ đọc phát có thể hiểu được ngay.

Ban đầu nó sẽ nhận request từ người dùng. Dạng như sau:

Nó sẽ đọc content và ghi vào 1 file gọi là main.php (cái này tuỳ vào ngôn ngữ được gửi lên. Nếu là php thì ghi vào file main.php. Nếu là javascript thì ghi vào file main.js).

Sau đó, web server sẽ gọi docker container để thực thi code bằng lệnh:

Cuối cùng sẽ đọc kết quả từ file /tmp/output và trả về cho người dùng với format response như sau:

Kết luận

Các bạn thấy thế nào? Có đơn giản không ak? Chỉ với 1 đoạn code ngắn mà chúng ta có thể dễ dàng viết được 1 chương trình code challenge rồi.

TechTalk via viblo.asia

  AI giành á quân trong cuộc thi thiết kế thời trang tại Trung Quốc
  Cuộc thi sáng tạo ACB WIN 2018 chính thức nhận bài dự thi
CHIA SẺ