Web chat sử dụng Spring Webflux và WebSocket

Em đang thử build một Web chat sử dụng Spring Webflux và WebSocket, nhưng đang vướng một vài vấn đề về bộ nhớ.

Khi em sủ dụng WebSocket trong Webflux thì có sử dụng Sinks.Many để lưu lại sự kiện sau đó sẽ gửi tới những người đã đăng ký những sự kiện mới. Có một vấn đề ở đây là khi em chạy stress test tầm 2000 kết nối trong vòng 1 phút chương trình thì lượng RAM bị tiêu thụ rất lớn, ngay cả khi không còn connection nào được kết nối cả. Sau đó một khoảng thời gian thì lượng RAM lại được giảm khá nhiều.
VD:
– Lúc bắt đầu chạy: 161 MB
Stress test lần 1:
– Sau khi có 2000 kết nối: 854 MB
– Khi không còn kết nối nào: 592 MB
Stress test lần 2:
– Tiếp tục 2000 kết nối: 592 MB -> 1290 MB
– Khi không còn kết nối nào: 1012 MB
Sau tầm 15-20 phút thì lượng RAM giảm về 686 MB
Còn một điều nữa là mặc dù không có kết nối nào, nhưng RAM vẫn cứ tăng nhẹ 0,1MB/1s sau khi stress test(đóng hết kết nối và server vẫn chạy)
Dưới đây là đoạn code của em. Không biết có cách nào để giải phóng RAM khi các kết nối đã ngắt không ạ?
Em xin đặt code ở link dưới cho nó dễ nhìn ạ
Link code

Cậu nên tuning JVM (cụ thể là GC). Nếu cậu buộc GC trigger sớm hơn, cậu sẽ nhanh giải phóng heap hơn. Cậu có thể cân nhắc giảm ngưỡng memory mà GC cần được kích hoạt để dọn dẹp, hoặc làm nhiều điều hay ho khác :smile:
Tuy nhiên, điều này cũng đồng nghĩa với việc cậu cần tăng CPU core lên. Nếu cậu có ít core, hẳn nhiên GC vẫn phải chờ CPU để thực hiện task dọn dẹp.

Về stress test cậu thực hiện, tớ có điều muốn hỏi:

  • Bottleneck của cậu phát hiện được là heap phải không?
    Check RAM không có ý nghĩa lắm đâu. Cậu nên check heap memory của JVM (mặc dù heap memory nằm trên RAM, nhưng rõ ràng không phải toàn bộ RAM được dành cho JVM heap memory).
  • Tớ không rõ mục tiêu stress test của cậu, cơ mà tớ có thể thấy 2000 long live connection là tình trạng rất cực đoan.
    1 long live connection sẽ giữ resource của cậu tương đối lâu, điều đó hẳn nhiên sẽ giữ reference của các object tương đối lâu.
    Khi đó, tuning JVM cũng sẽ không có ý nghĩa, vì GC không thể dọn dẹp được object nếu nó vẫn còn reference tới object đó.
    Khi tất cả các kết nối đã tắt, nếu cậu tuning JVM đúng, GC nên được trigger sớm nhất có thể.
    Nếu như đó là điều kiện mà cậu thường có trên production, cậu nên add thêm resource cho server (thêm heap, thêm CPU, hoặc thêm instance cho cluster).
    Cơ mà tớ nghĩ đó không phải điều kiện mà production đang trải qua, vì cậu nói cậu đang stress test :smile:
  • Khi chạy xong test mà cậu vẫn còn thấy heap tăng lên (kiểm tra xem đó là heap hay không nhé! :smile: RAM tăng chưa chắc đã là do JVM đâu), thì khả năng cao cậu có memory leak.
    Cậu thực sự nên profile app của cậu để tìm chỗ leak đó.

Hope it helps!

8 Likes

Em cảm ơn anh rất nhiều về những lời khuyên này ạ.

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?