Hoàn cảnh
Chào mọi người, nay mình vừa fix xong một cái bug do sự bất cẩn của mình gây ra. Sau hai ngày liên tục, "khó ăn khó ngủ" cuối cùng mình cũng. Tuy nhiên, nó khiến mình nhận ra khá nhiều vấn đề, mình khá là tâm đắc nên muốn lên đây để chia sẻ.
Trước tiên thì nói về bug mà mình dính phải, mình xây dựng một tính năng cho một hệ thống tạm gọi "ABCxyz", trong đó có việc phải viết một API để upload file pdf lên server. Nghĩ thì đơn giản, nó cũng tương tự như những API mình từng viết để upload image (Mình dùng file upload với Multer, Nodejs và Express) chỉ cần copy code, sửa lại type, name một là xong rồi.
Chuyện là hệ thống này đã release và chạy khá ổn định. Nên mình đã đóng test server ( Mình config thêm con server để có thể test được môi trường như production), và những tính năng được bổ sung sau này, mình rất tự tin vào bản thân, tự tin vào local =)). Và rồi, bùm, khi lên production, nó bị lỗi. Sau khi mình upload file pdf đó, thì cũng call API method POST, truyền dữ liệu file vào, rồi nó gửi lên server, upload cái file có vài MB mà loading nó quay vòng vòng. Mình tưởng mạng lag =)) ngồi đợi, đợi hết mấy phút thì bị timeout, trả về status code 504. Nói qua, là bản thân mình tự build một hế thống này từ A-Z, chưa từng được hướng dẫn bài bản, mình có base lập trình từ trường, tự học qua mọi thứ rồi mình ghép lại. Từ cái nhỏ nhất như là cắt HTML CSS từ design, code logic FE, BE rồi mò mẫm đi mua domain, thuê VPS, rồi cấu hình nginx, CDN, DB để vận hành website (dù trước đó, mình chỉ có kinh nghiệm 2 tháng thử việc ở một cty, SSH vào server, cấu hình nginx như là một khái niệm lạ với mình). Dạo này nhanh trí thay vì search GG thì mình hỏi chatGPT, mình khá tin tưởng con chatbot này về mảng tech, vì đa số các công nghệ mình hỏi, sẽ có documentation, và tất nhiên nó trả lời khá thông minh, nhưng rồi mình cũng chả biết lỗi ở đâu.
Vậy lỗi 504 là gì?
Ngắn gọn đơn giản là nó bị timeout, server không phản hồi, vậy thôi. Hiểu một cách đơn giản, là khi bạn call một API lên server và nhận được phản hồi là "đíu" nhận phản hồi yêu cầu đó.
Với tư duy logic thượng thừa, khả năng fix bug thần sầu, mình nghĩ chắc thẳng CDN (mình dùng cloudflare) hay nginx nó bị lỗi, hay sao sao đó, không connect nhau được rồi bị timeout chứ gì. Lên dashboard Digital Ocean (nơi mình thuê VPS, DB), thấy có thông báo cáp biển rồi gói tin khu vực châu Á có thể bị mất, nhảy qua thằng cloudflare status thì thấy lịch bảo trì =)) mà hình kp bảo trì khu vực của mình. Do sự ngu ngốc và chủ quan thái quá, vậy chắc là lỗi của hai cái nhà cung cấp này rồi, thôi đợi mai check lại, dù sao thì nay chưa lên tính năng được thì mai lên .
Rồi mai, vẫn vậy, khá là hoang mang, vì thực sự tư duy mình lúc đó, nếu thực sự lỗi không phải ở hai nhà cung cấp đó, thì mình chả biết phải làm như nào? Vậy thôi đi cf, đi chơi game. Mình đã xen kẽ thời gian và suy nghĩ của mình. Mình đã làm gián đoạn suy nghĩ của mình về cái việc fix bug, đúng kiểu là vội thì vội nhưng phải từ từ. Vì vội éo có ra được =)). Đó là kinh nghiệm mình đúc rút ra từ những lần fix bug trước. Tại vì mình sẽ liên tục nghĩ về việc đó, nếu nghĩ liên tục trong một thời gian khá lâu, cái góc nhìn của mình sẽ càng chủ quan và phiến diện, sẽ dần dần đi theo một chiều và khẳng định nhất định là nó, chính là nó rồi khi biết nó không phải là vấn đề thì sẽ suy sụp =)). Rồi thì mình cũng nhận ra, ủa tất cả các API, rồi hệ thống (server, DB, CDN) ngoại trừ API đó, nên mình mở code kiểm tra lại, chứ tại vì mình test trên local, oke rồi.
Rốt cuộc là lỗi gì?
Khi upload image, mình đã tự hiện thực button upload, có preview hình trước khi upload, tự viết dùng axios call API gửi lên server. Nhưng khi upload pdf, mình đã dùng Upload Component của Antd, rất hay rất tiện, tuy nhiên, vấn đề xảy ra lúc này là nó là method POST type multipart/form-data , cho phép gửi file, và mình muốn gửi kèm thêm 1 cái field ID, thì cái InterfaceProps của antd nó không có tồn tại field query để mình thêm vào. Nhanh trí, mình nghĩ tới dùng query params, chèn thêm ví dụ như ?id=12312312 vào URL nhưng thấy củ chuối và không chuyên nghiệp nên mình quyết định, sẽ gửi nó thông qua headers. Ơ một fullstack developer, à nhong, full tất cả, full mọi thứ miễn là chạy được đã làm vậy. Mình đã thêm một field cho headers trước khi call API, và rồi ở backend local, mình vẫn nhận được id đó, và mọi thứ thành công tốt đẹp ở local haha =)), còn lên production, nó phải đi qua cloudflare, đi qua nginx. Và hình như cái field đó bị xóa ở giai đoạn nào thì mình không có rõ. Một kiến thức mà sau 2 ngày mới được tiếp thu đó là, các field của header có thể bị xóa hoặc chỉnh sửa khi đi qua các proxy server, và hãy nhớ tìm hiểu kĩ kiến thức chứ mình thì cứ chạy được đã rồi sẽ có kinh nghiệm =)). Tuy vậy, vẫn chưa giải thích được là tại sao lỗi 504. Và lỗi 504 là sự chủ quan của bản thân mình, khi mình dựng API, sẽ có một số trường hợp, nếu như không tìm thấy dữ liệu, mình sẽ k trả kết quả về. Lúc đó chắc lười, nên nghĩ vậy, rồi còn tự bao biện, lỡ thằng nào muốn phá mình, call API để check này check kia, rồi nó éo thèm trả lời chắc cay cú lắm, cũng là tính năng bảo mật. Đấy =)) rồi mình cay cú đấy, đã lười còn bao biện cho sự lười đó. Và khi field của mình bị xóa, tiếp theo đó là không tìm được dữ liệu, và server không phản hồi, vậy là timeout.
Tổng kết
Rút ra được những gì:
- Nếu lỗi 504, nếu không phải do CDN hay proxy server thì hãy kiểm tra logic của bạn, có thể do có một trường hợp bạn quên response và thế là timeout.
- Viết code cẩn thận, theo các tiêu chuẩn sẵn có, nếu chưa biết thì tìm hiểu, nó không quá khó, lúc đầu có thể chậm những về sau bạn sẽ đỡ được rất nhiều thời gian, đừng có lười, lười là về sau bỏ cuộc đấy =)) hoặc là đập đi xây lại như mình.
- Khi giải quyết một vấn đề lớn, thứ nhất hãy nhìn tổng quan trước, đưa rất tất cả khả năng gây ra lỗi, rồi từ từ loại bỏ dần những khả năng không có, cuối cùng là kiểm tra lại những khả năng gây ra lỗi. Tuy nhiên, nếu như sau khi kiểm tra tất cả, mà bạn vẫn không tìm ra lỗi. Hãy đi hỏi người khác. Mình đã hỏi anh Leader của mình, và nhận được một gợi ý về việc tăng timeout cho server nhưng gợi ý này chỉ đúng khi bản thân mình code đúng ( là dù không tìm thấy dữ liệu hay bị lỗi gì thì cũng nên trả một response). Và rồi vì là dự án ngoài nên mình k thể share hay là hỏi ảnh thật kĩ được. Nên cắm đầu fix bug tiếp rồi mới có bài viết ngày hôm nay.
- Và nhớ là các field của header có thể bị xóa hoặc chỉnh sửa khi đi qua các proxy server. Hãy tìm hiểu về các header tiêu chuẩn, syntax và công dụng của nó nhé hỡi các backend developer =))
Mình rất may mắn khi dám nhận dự án này, và cũng trải qua rất nhiều thử thách, khi phải thực sự xây dựng nó từ con số 0, và hiện tại là vận hành và phát triển nó. Có lẽ đây là bài đầu tiên trong series chia sẻ kinh nghiệm, một số những điều hay khi mình tự ngộ ra được trên hành trình tự học lập trình của mình.
Rất cảm ơn viblo, đã tạo ra một cộng đồng, giúp mọi người chia sẻ câu chuyện, góc nhìn và kiến thức. Mình cũng hay copy code ở trên này đấy =)) xào xào chút là thành của mình thôi :v Hi vọng sẽ có những bài viết tiếp theo và được ủng hộ.