Làm thế nào để đảm bảo website hoạt động trơn tru và không bị mất dữ liệu khi xảy ra sự cố?

  1. Lập trình

  2. Công nghệ thông tin

Hí anh em. Lại là mình đây. Nay mình muốn chia sẻ 1 chút kinh nghiệm cá nhân. Khi phát triển phần mềm, ứng dụng web, app,… thì 1 trong những thứ tối quan trọng là đảm bảo sao cho website luôn hoạt động ổn định, không bị mất dữ liệu người dùng khi đã truy cập vào website. Đặc biệt là các website có lượng traffic lớn, thì việc hệ thống sập & mất dữ liệu người dùng là việc rất nghiêm trọng.

https://cdn.noron.vn/2021/04/27/49301135312574280-1619490018_1024.png

Vậy nên làm thế nào để đảm bảo hệ thống hoạt động trơn tru, luôn có thể backup data trong trường hợp xảy ra sự cố? Hôm nay mình xin chia sẻ 1 số phương pháp sau. Có gì nhờ ae đóng góp thêm 😀

1. Đảm bảo server chạy ổn định

1.1 ĐỊNH KỲ KIỂM TRA WEBSITE

Khi người dùng gõ tên domain của bạn lên trình duyệt, hoặc truy cập tới từ 1 nguồn của bên thứ 3 ( Facebook, Google, Zalo, …). Lúc này DNS server sẽ phân giải từ tên miền ra địa chỉ IP của web server bạn và thực thi HTTP Request tới đó. Trong giai đoạn này nếu web mà xảy ra lỗi thì gặp ông vải luôn :)) ko có cách nào backup cả. Vì user còn chưa kịp đến website của bạn. Trong trường hợp này cách tốt nhất để giảm thiểu rủi ro là dùng cronjob định kỳ kiểm tra website( cũng có thể check bằng cơm nhưng mình k khuyến nghị lắm nhé :)) ), nếu thấy có bất thường thì sẽ gửi thông báo cho Dev để kiểm tra. Dưới đây mình dùng chức năng Automated Test của

Laravel Dusk

try {
    $this->browse(function (Browser $browser) {
    $date = date('Y_m_d__H_i_s');
    $folder = date('Y-m-d');
    $browser->visit('https://xxxx.vn')
       ->pause(1000)
       ->type('input[name="username"]', 'nampth')
       ->type('input[name="password"]', 'deptrai')
       ->press('#m_login_signin_submit')
       ->waitForLocation('/home')
       ->assertPathIs('/home')
       ->screenshot("$folder/automated_check_$date")
       ->quit();
} catch (\Exception $e) {
     Notification::route('slack', env('SLACK_HOOK'))
         ->notify(new QueryError("Automated web check failed"));
     throw $e;
 }

Như đoạn code trên thì định kỳ mình sẽ chạy 5p 1 lần, truy cập vào trang web, login thử và kiểm tra xem nó có redirect đến /home không và chụp màn hình. Nếu có lỗi trong quá trình này thì sẽ gửi thông báo qua slack. Như vậy sẽ đảm bảo việc hệ thống chạy trơn tru, nếu chết thì cùng lắm 5p thôi :))

Ngoài ra ae cũng có thể dùng thằng Dusk này để check API nhé. Automated các trường hợp xem response có ok không & gửi notification thôi.

1.2 THỰC HIỆN LOAD BALANCING

Cơ chế Load Balancing chắc không còn quá mới lạ với các lập trình viên web. Việc cân bằng tải này vừa giúp giảm thiểu áp lực lên server khi lượng CCU cao & vừa đảm bảo tính ổn định của hệ thống khi website xảy ra vấn đề.

Có nhiều cách để thực hiện Load Balancing, nhưng như hiện tại thì mình thấy có 2 cách phổ biến: free & trả phí.

Nếu với lượng người dùng vừa phải, kinh phí hạn hẹp thì mình khuyên ae nên nghiên cứu cơ chế Round Robin của Nginx. Nginx là 1 webserver rất thông dụng & cung cấp khá đầy đủ các dịch vụ cho 1 lập trình viên. Ae có thể tham khảo thêm ở Docs của nó tại

đây
, mình xin phép không đi sâu vào phần này.

Còn với trường hợp dùng trả phí, ae có thể tham khảo dịch vụ Load Balancing của Cloudflare. Hiện tại mình đang dùng gói 5$ 1 tháng, Cloudflare sẽ cung cấp cho 2 địa chỉ để mình trỏ domain tới, cấu hình lượng traffic cho mỗi domain, … mọi thứ đều qua giao diện & khá dễ sử dụng. Ae chỉ việc vào tab Traffic/Load Ballancing tạo Pool & Origin thôi. Rất dễ sử dụng.

https://cdn.noron.vn/2021/04/27/2571215882310249-1619490464_1024.png

1.3 ĐỊNH KỲ KIỂM TRA CPU/MEM/FREE DISK SPACE CỦA WEBSERVER

Việc này đôi ae ít để ý nhưng là 1 vấn đề khá quan trọng, đặc biệt là với 1 PHP dev như mình 🙁 Khi lượng người dùng online (CCU) cao hoặc bị Dos/DDos, web server sẽ chịu nhiều HTTP Request & thực thi, tính toán,trả dữ liệu dẫn tới CPU/Mem tăng cao, làm cho website bị chậm. Hoặc đôi khi chỉ là Log, dữ liệu trên server nhiều quá dẫn tới việc đầy ổ cứng cũng là nguyên nhân làm cho Webserver bị ảnh hưởng. Vấn đề này các nhà cung cấp hosting đa phần đều có hỗ trợ. Ví dụ thằng Digital Ocean thì ae tham khảo thêm tại

đây
nhé. Tính năng này mình chưa dùng nhiều nên không dám viết láo :)) ae thông cảm

2. Lưu log, lưu log & Lưu log mọi lúc , mọi thứ có thể.

Có rất nhiều cách lưu, dưới đây mình xin chia sẻ 1 số cách lưu log thông dụng theo từng giai đoạn người dùng truy cập vào website, tương ứng với việc 1 người dùng thực hiện 1 HTTP Request. Việc lưu Log này sẽ giúp cho các bạn đảm bảo hệ thống hoạt động trơn tru, có thể backup dữ liệu trong trường hợp server xảy ra lỗi, hoặc giảm thiểu mức thấp nhất việc mất dữ liệu người dùng khi xảy ra vấn đề.

2.1. CẤU HÌNH WEBSERVER

Sau khi qua các bước ở phần 1 thì server chạy đã khá ngon nghẻ rồi. Người dùng đã có thể truy cập vào website của bạn. Lúc này ae có thể setup Log qua các dịch vụ web server. Ví dụ như với Nginx, ae có thể setup log format để lưu thông tin người dùng truy cập như sau:

http {
    log_format upstream_time '$remote_addr - $remote_user [$time_local] '
                             '"$request" $status $body_bytes_sent '
                             '"$http_referer" "$http_user_agent"'
                             'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';

    server {
        access_log /spool/logs/nginx-access.log upstream_time;
        ...
    }
}

Như phần cấu hình ở trên chúng ta đã lưu thông tin về Header, địa chỉ IP, UserAgent,… và các thông tin khác. Phục vụ cho nhiều mục đích sử dụng sau này. Ví dụ như để phân tích thuộc tính người dùng sử dụng web, điều tra hành vi người dùng, xem thông tin request nếu bị Dos/DDoss. Ae có thể tham khảo chi tiết thêm về cấu hình Nginx tại

đây
nhé

2.2 LƯU TRỮ LOG TRƯỚC KHI GỌI CÁC API

Mình lấy ví dụ bạn làm 1 website bán thuốc tân dược và để lại form cho KH điền SDT, sau đó sẽ chăm sóc bằng Telesale. Tuy nhiên xảy ra 1 số trường hợp API bị lỗi KH không submit được form => mất thông tin KH

Để giải quyết vấn đề này, mình sử dụng 1 kỹ thuật khá cũ là 1pixel. Tức là sẽ thực hiện 1 http request backup lên server của mình, trong đó lưu trữ lại các thông tin của KH.

let sid = localStorage.getItem('nuxt_sid');
    postData.sid = sid;
    let queryString = Object.keys(postData).map(key => key + '=' + postData[key]).join('&');
    if (document.getElementById('pixel-wrapper')) {
        document.getElementById('pixel-wrapper').innerHTML = '<img class="hidden"  src="https://abcd.vn/log.png?' + queryString + '">';
    }

Sau khi thực hiện đoạn code này. Trên access log của nginx sẽ có 1 bản log dạng

[DateTime] abcd.vn/log.png?sid=werwerewr&name=nampth&sdt=012345678

Ngon rồi. Như vậy trước khi gọi API mình đã kịp backup lại thông tin KH lên đây. Sau này chỉ việc so khớp số lượng KH & kiểm tra trong nginx xem thông tin KH đã có trong DB chưa => nếu chưa có có thể API lỗi thì mình insert vào thôi 😀

2.3 LƯU TRỮ LOG API

Giả sử việc bạn gọi API không vấn đề gì , User có thể gửi thông tin vào API của bạn, thì mình khuyến nghị vẫn nên lưu thông tin API nhé. Như mình đang dùng Laravel thì sẽ sử dụng Middleware để lưu log, tránh trường hợp insert vào DB bị lỗi dẫn tới mất dữ liệu.

Có nhiều cách để lưu log: file, elastic search, DB, … nhưng theo mình thấy tiện nhất & hiệu quả nhất thì sẽ ghi ra file & định kỳ update log vào DB. Việc này đảm bảo cho API của bạn không phải chờ ghi việc ghi log vào DB, ES, và cũng đảm bảo cho việc quản lý Log nữa. Nếu ae ghi thẳng vào DB, ES, … thì đôi khi API sẽ phải chờ thêm đoạn ghi log. Mà với 1 thằng không hỗ trợ quản lý connection pool Mysql như php thì đây là 1 ý kiến khá tệ 🙁

3. Định kỳ backup CSDL

Một trong những phần khá quan trọng. Định kỳ backup CSDL chủ yế để phòng rủi ro website bạn bị tấn công, xóa database hoặc hacker mã hóa DB của bạn và bắt trả BTC để được giải mã ( thường thì có trả BTC nó cũng ko trả đâu. hix). Giao diện web có thể lấy từ Git còn DB mà không backup thì chịu ae ạ.

Việc này ae nếu dùng wordpress thì có sẵn rất nhiều plugin hỗ trợ. Còn nếu các framework khác thì có thể viết file sh, hoặc chạy cronjob định kỳ backup cũng được. Nhớ là backup sang server khác hoặc lên cloud nhé chứ để ở cùng hosting mà bị chiếm quyền thì cũng mất toi :))

Nếu dùng sh file thì ae có thể search google nhớ, hoặc tham khảo luôn ở

post này trên stackoverflow

4. Kết

Sau các bước này thì gần như đã có thể đảm bảo việc dữ liệu luôn thông suốt rồi. Và nhờ việc lưu log & backup đầy đủ thì ae có thể yên tâm việc đảm bảo tính toàn vẹn và sẵn dùng cho ứng dụng web 😀 Có gì mong ae góp ý thêm ạ. Mình cảm ơn

https://cdn.noron.vn/2021/04/27/49301135312574287-1619490613_1024.png
Từ khóa: 

lập trình

,

công nghệ thông tin