Vấn đề với bộ nhớ của serverless - Deno Deploy

Vấn đề với bộ nhớ của serverless - Deno Deploy

Những mẩu tin ngắn hàng ngày dành cho bạn
  • countless.dev là một trang web khá thú vị khi mà nó so sánh giá tiền sử dụng các mô hình LLMs của các nhà cung cấp khác nhau.

    Tại đây bạn có thể nhìn thấy tất cả các mô hình ngôn ngữ lớn phổ biến bởi các nhà cung cấp như OpenAI, Azure, Mistral... Bảng giá cho mỗi 1M tokens đầu vào/ra. Hoặc thậm chí có thể so sánh chúng với nhau để tìm ra nhà cung cấp hoặc mô hình rẻ nhất tuỳ theo mục đích sử dụng.

    » Xem thêm
  • 1,2 năm trước, Kubernetes (k8s) tự nhiên được nhắc đến như một hiện tượng, chắc vì nó bá quá nên ai cũng muốn học và sử dụng. Nó là một công cụ "Automating deployment, scaling, and management of containerized applications" - Vâng! nghe hay ho đấy chứ 🤤.

    Hồi đó thì mình đang đam mê với Docker, đặc biệt là Docker Swarm, cũng tương tự như k8s ý nhưng ở quy mô nhỏ hơn. Docker Swarm thì có vẻ ít phức tạp hơn nhiều so với k8s. Mà như thế cũng tốt vì nó đã và đang đáp ứng rất tốt nhu cầu sử dụng của mình lúc đó, lại còn bớt đi phần phức tạp, lằng nhằng.

    Ấy thế mà 1-2 tháng trở lại đây, các bài viết có tiêu đề "bạn có thực sự cần đến Kubernetes" lại đang nổi lên với tần suất dày hơn. Quả thật k8s rất mạnh nhưng cũng quá phức tạp. Tại sao phải cố dùng dao "mổ trâu để giết gà" cơ chứ? Trừ khi bạn lường trước được độ phức tạp khi muốn áp dụng một công nghệ. Một cái nữa k8s tiêu tốn tài nguyên và nguồn lực ghê ghớm, để vận hành được nó không đơn giản là dựng lên được là xong mà còn phải có rất nhiều nhiều kiến thức nữa 😨.

    À, chắc cũng một phần nữa là do các "ông lớn" đang tập trung đẩy mạnh vào Serverless, giảm bớt sự phức tạp trong khâu vận hành đi, thay vào đó là nên tập trung vào phát triển ứng dụng.

    Bên cạnh đó, thì cái tên WASM cũng đang được nhắc đến rất là nhiều 🤔

    Do you really need Kubernetes in your company/startup? | dev.to

    Do You Really Need Kubernetes?

    » Xem thêm
  • Trước mình cứ khen lấy khen để Serverless, rằng tối ưu chi phí xuống 0đ để duy trì blog các thứ. Đúng là như vậy thật! Nhưng bên cạnh đó serverless cũng có các mặt tối đáng để lưu tâm đấy!

    Hôm kia mình phải mất ngày trời để truy tìm và khắc phục sự cố chỉ vì gọi hàm build-in của Cloudflare KV. Cụ thể là hàm list với limit 1000 - tức là một lần gọi nó trả về 1000 keys của KV. Cơ mà đời không như là mơ. Con số 1000 chỉ là trên lý thuyết. Lúc thì trả về vài trăm, lúc thì vài chục, thậm chí lúc thì lẹt đẹt có vài cái. Thế là làm tắc nghẽn cả hệ thống. À mà cũng không phải là nghẽn mà là hệ thống "nhàn rỗi" quá không có việc gì để làm, trong khi thực tế đáng ra nó phải xử lý cả trăm ngàn cái keys cơ 🥲

    » Xem thêm

Vấn đề

Hà Nội đã bước vào mùa thu, thời tiết không còn nắng nóng khắc nghiệt như ngày hè nữa mà thay vào đó là những cơn mưa xen kẽ. Mưa tắc đường, ngập lụt, còn hại biết bao nhiêu người. Ghét cái tiết trời thế này thật!

Hơn nửa tháng nay cơ thể tôi khá "mềm mỏng", pha một chút uể oải và rã rời. Nó không muốn phải vận động nhiều, kéo theo đó là cả phong độ đi xuống. Nhiều hôm đi làm về chỉ muốn nằm lì một chỗ, hoặc ngủ luôn cũng được. Sáng mai thức dậy cơn đau đầu thi thoảng còn ghé đến thăm, năng suất làm việc của ngày hôm đó phải giảm đi một nửa 🫣

Cách đây không lâu, trong bài viết Đập đi xây lại có đề cập đến việc viết lại blog từ Nuxt sang Fresh để giảm thiểu mã JavaScript và tăng tốc độ tải trang. Bên cạnh đó là chuyển nhà từ Cloudflare Worker sang Deno Deploy đơn giản vì Cloudflare chưa hỗ trợ Fresh. Quá trình diễn ra suôn sẻ và nhanh chóng vì đã có kinh nghiệm triển khai dự án lên serverless từ trước đó.

Deno Deploy vẫn còn khá mới. Thi thoảng tôi nhận được báo cáo trang web bị sập từ các công cụ theo dõi. Mà điều này thì chưa từng xảy ra ở Cloudflare. Thiết nghĩ đã trên serverless rồi mà còn bị dính downtime thì quả là một điều tối kỵ. Nhưng không sao, nó không diễn ra quá thường xuyên và thường được khắc phục rất nhanh sau đó.

Gần đây, đã có một số độc giả nhắn tin trực tiếp cho tôi phản ánh về một số bài viết không thể truy cập vào được. Sau khi kiểm tra thì có vẻ như nó đã sử dụng hết bộ nhớ. Mỗi khi truy cập, màn hình logs xuất hiện một thông báo "Memory limit exceeded, terminated". Hmm... điều này trước đến nay cũng chưa từng xảy ra ở Cloudflare.

Memory limit exceeded

Như các bạn biết, serverless có cách phân bổ bộ nhớ không giống với máy chủ truyền thống. Chúng ta không thể can thiệp được vào việc cấp phát tài nguyên mà chỉ được phân bổ một lượng nhất định từ nhà cung cấp. Ví dụ mỗi một request đến thì chỉ được xử lý trong 512Kb bộ nhớ cộng với 50ms xử lý của CPU chẳng hạn. Nếu vượt quá, bạn phải trả thêm tiền để nâng cấp hoặc phải nhận thông báo lỗi giống như tôi.

Vậy thì vấn đề nằm ở logic, có thể mình đang lấy quá nhiều dữ liệu hoặc tạo ra quá nhiều biến khiến cho bộ nhớ sử dụng bị tăng lên. Nhưng có một điều lạ là không phải bài viết nào cũng bị lỗi này. Sẽ có bài bị bài không bị và điểm chung của những bài bị lỗi là nội dung thường chứa nhiều block code của markdown.

Sau khi xem xét lại mã, tôi nghĩ rằng vấn đề nằm ở hàm convertMarkdownToHTML. Hàm này có chức năng chuyển đổi văn bản markdown thành HTML để cho trình duyệt hiển thị. Các bài viết đang được để ở văn bản markdown, và với mỗi lần đọc bài viết, convertMarkdownToHTML lại được gọi.

Bên trong convertMarkdownToHTML còn có thư viện showdown-highlight để áp dụng cú pháp "tô sáng" vào những nơi có sử dụng block code. Thay vì những dòng chữ đơn điệu màu đen thì khi áp dụng highlight vào, đoạn code sẽ trở nên có màu sắc hơn. showdown-highlight áp thêm một số đoạn mã html kèm các thẻ css để thêm màu sắc. Vì thế tôi nghĩ vấn đề nằm ở đây, block code càng nhiều thì lượng ký tự thêm vào càng nhiều. Nếu cắt bớt các đoạn block code này hoặc giảm thiểu cú pháp tô sáng xuống thì nhiều khả năng sẽ giảm được dung lượng bộ nhớ.

Sau khi áp dụng với 1-2 bài thì lỗi không còn xuất hiện nữa. Tôi càng tin suy đoán của mình là đúng. Nhưng chưa kịp thở phào nhẹ nhõm thì sau khi mở Google Console, thật bất ngờ khi thấy số lượng bài viết gặp gặp lỗi nhiều hơn rất nhiều so với con số mình biết. Nếu tiếp tục áp dụng cách trên thì bài viết sẽ dần bị mất "chất". Vì loại bỏ block code đồng nghĩa với chất lượng bài viết bị giảm đi đáng kể, viết về lập trình mà không "show code" thì nói ai tin!?

Hmm, chẵng lẽ việc lấy dữ liệu từ database ra thôi mà đã hết bộ nhớ rồi sao?

Tôi thậm chí còn xem lại xem việc dữ liệu lấy dữ liệu từ database có làm tăng kích thước bộ nhớ không. Vì ngoài hàm convertMarkdownToHTML ra thì vẫn còn nhiều đoạn mã lấy bài viết gợi ý, lấy bình luận, cùng nhiều biến được tạo ra để xử lý logic... Nếu nhiều như vậy thì có lẽ nào phải ngồi cân đo đong đếm từng biến để xem chúng đang chiếm bao nhiêu bộ nhớ sao?

Một bước ngoặt lớn khi tôi phát hiện ra một bài viết rất ít chữ cũng gặp phải tình trạng tương tự. Điều đó cho thấy vấn đề không phụ thuộc vào độ dài ngắn của nội dung bài viết mà có thể là do một đoạn mã nào đó đang sử dụng bộ nhớ nhiều hơn. Như vậy, phải có cách nào đó soi được quá trình cấp phát bộ nhớ trong của Deno thì mới xác định được vấn đề nằm ở đâu.

Dev Tools trong trình duyệt có một công cụ giúp chúng ta theo dõi được lượng bộ nhớ đã được phân bổ. Mở Dev Tools, vào "Memory" và nhìn vào tuỳ chọn "Allocation sampling", nó cho phép chúng ta quan sát được bộ nhớ được cấp phát trong quá trình chạy. Thật may mắn vì Deno vẫn sử dụng V8 nên bật debug thì sẽ sử dụng được tính năng này.

Dev Tools Memory

Tôi tìm cách bật debug trong Deno. Thật đơn giản, chỉ cần thêm cờ --inspect vào trước lệnh run thì quá trình debug rất giống với Node.js.

Tại đây, sau khi soi Chart thì đúng là hàm convertMarkdownToHTML đang sử dụng rất nhiều bộ nhớ, lên đến 86% tổng bộ nhớ trong phiên xử lý này. Khi so sánh với bài viết không gặp lỗi, thì con số chỉ ở mức hơn 20% một chút. Tiếp tục soi vào bên trong convertMarkdownToHTML thì hoá ra thư viện showdown cần nhiều bộ nhớ để parse markdown sang HTML. Cuối cùng tôi có thể kết luận rằng bài viết nào sử dụng thẻ markdown càng phức tạp thì khả năng lỗi càng cao.

Phân tích hàm parse markdown

Phân tích hàm parse markdown 2

Đến đây nhiều người nghĩ nên đổi sang thư viện khác. Nhưng tôi thì ngược lại, một phần vì đã mất công cấu hình thư viện này parse một số đoạn mã phức tạp theo cách mà mình muốn. Nếu đổi sang thư viện khác thì phải tìm cách parse lại nội dung giống như thế, tốn thời gian, cả chưa kể rủi ro về việc phá vỡ parse mã trong các bài viết khác.

Vậy cách khả thi nhất vẫn là gỡ service parse markdown hiện tại ra, không gọi hàm convertMarkdownToHTML mỗi khi render bài viết nữa. Thay vào đó là tạo thêm một cột lưu lại nội dung dạng HTML trong mỗi bài viết.

Chỉ với vài dòng code, tôi tách được hàm convertMarkdownToHTML sang một project sử dụng hono.dev và triển khai nó lên Cloudflare Worker. Sau đó thêm logic ở API tạo/cập nhật bài viết, chuyển hàm convertMarkdownToHTML thành một cuộc gọi API sang service mới, lưu lại nội dung HTML mới. Đồng thời bỏ hàm convertMarkdownToHTML cũ đi.

Mọi thứ đã hoạt động trở lại!

Tổng kết

Qua vấn đề này mới thấy tài nguyên trong serverless là hữu hạn, không được sử dụng thoả thích như trong máy chủ. Cần phải cẩn trọng trong khâu xử lý dữ liệu, mọi thứ cần phải được tối ưu nhất có thể nếu không muốn gặp phải phiền toái trong quá trình vận hành.

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.
Author

Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.

Bạn thấy bài viết này có ích?
Không

Bình luận (0)

Nội dung bình luận...