ಒಂದು ಭಾರಿ ಚಾಟ್ ನಮ್ಮ API ಅನ್ನು ಹೇಗೆ ನಿಲ್ಲಿಸಬಹುದಿತ್ತು
ಸೆಪ್ಟೆಂಬರ್ 28 ರಂದು, ಬಿಡುಗಡೆಯ ಸುಮಾರು 17 ನಿಮಿಷಗಳ ನಂತರ, ನಮ್ಮ ಎರಡೂ ಉತ್ಪಾದನಾ API ಸರ್ವರ್ಗಳು ಒಂದೇ ಕ್ಷಣದಲ್ಲಿ ಮೆಮೊರಿ ಖಾಲಿಯಾಗಿ ಮರುಪ್ರಾರಂಭಗೊಂಡವು, ಮತ್ತು ಸುಮಾರು ಐದು ನಿಮಿಷಗಳ ಕಾಲ ಲೋಡ್ ಬ್ಯಾಲೆನ್ಸರ್ಗೆ ಟ್ರಾಫಿಕ್ ಕಳುಹಿಸಲು ಆರೋಗ್ಯಕರ ಸರ್ವರ್ ಇರಲಿಲ್ಲ. ನಮ್ಮ ಮೊದಲ ಪರಿಹಾರ API ಗೆ ಎರಡು ಪಟ್ಟು ಮೆಮೊರಿ ನೀಡಿತು. ನಿಜವಾದ ಕಾರಣ ಅದೇ ದಿನ ನಂತರ ಬಯಲಾಯಿತು: ಒಂದು ನಿರ್ದಿಷ್ಟ ಚಾಟ್ ತೆರೆಯುವುದು API ಗೆ ಒಂದೇ ವಿನಂತಿಯಲ್ಲಿ 53 MB ಸಂದೇಶಗಳನ್ನು ಲೋಡ್ ಮಾಡಲು ಕೇಳುತ್ತಿತ್ತು. ಈಗ ಚಾಟ್ ಇತಿಹಾಸ ಸಂಖ್ಯೆ ಮಾತ್ರವಲ್ಲ, ಗಾತ್ರದ ಮಿತಿಯೊಂದಿಗೆ ಪುಟಗಳಲ್ಲಿ ಲೋಡ್ ಆಗುತ್ತದೆ, ಮತ್ತು ಆ ಚಾಟ್ ಈಗ ಕ್ರ್ಯಾಶ್ ಆಗದೆ 5 MB ಮೊದಲ ಪುಟದೊಂದಿಗೆ ತೆರೆಯುತ್ತದೆ.
ಏನು ಸ್ಥಗಿತಗೊಂಡಿತು
ನಮ್ಮ API ಲೋಡ್ ಬ್ಯಾಲೆನ್ಸರ್ ಹಿಂದೆ ಎರಡು ಸರ್ವರ್ಗಳಲ್ಲಿ ಪ್ರತಿಯೊಂದರಲ್ಲಿ ಒಂದು ಕಂಟೈನರ್ ಆಗಿ ನಡೆಯುತ್ತದೆ. ಪ್ರತಿ ಕಂಟೈನರ್ಗೆ 384 MiB ಮೆಮೊರಿ ಮಿತಿ ಇತ್ತು. ಸುಮ್ಮನೆ ಇರುವಾಗ ಅದು 130–140 MiB ಬಳಸುತ್ತದೆ, ಆದ್ದರಿಂದ ಮಿತಿ ಸಾಕಷ್ಟು ಹೆಚ್ಚುವರಿ ಸ್ಥಳದಂತೆ ಕಂಡಿತು.
ಎರಡೂ ಕಂಟೈನರ್ಗಳು ಒಟ್ಟಿಗೆ ಆ ಮಿತಿಯನ್ನು ತಲುಪಿ “JavaScript heap out of memory” ನೊಂದಿಗೆ ಕ್ರ್ಯಾಶ್ ಆದವು. ಹೀಪ್ ಎಂದರೆ Node.js ಪ್ರಕ್ರಿಯೆ ತನ್ನ ಕೆಲಸದ ವಸ್ತುಗಳಿಗಾಗಿ ಬಳಸುವ ಮೆಮೊರಿ. ಎರಡೂ ಸರ್ವರ್ಗಳು ಒಂದೇ ಸಮಯದಲ್ಲಿ ವಿಫಲವಾದ್ದರಿಂದ, ವಿನಂತಿಗಳನ್ನು ಕಳುಹಿಸಲು ಎಲ್ಲಿಯೂ ಉಳಿದಿರಲಿಲ್ಲ. ಎರಡು ಸರ್ವರ್ ಇರುವ ವ್ಯವಸ್ಥೆಗೆ ಇದು ಅತ್ಯಂತ ಕೆಟ್ಟ ರೀತಿಯ ಸ್ಥಗಿತ: ಪುನರಾವರ್ತನೆ ಆಗ ಮಾತ್ರ ಸಹಾಯ ಮಾಡುತ್ತದೆ, ವೈಫಲ್ಯಗಳು ಒಂದೇ ಸಮಯದಲ್ಲಿ ಸಂಭವಿಸದಿದ್ದರೆ.
ಮೊದಲ ಪರಿಹಾರ: ಹೆಚ್ಚು ಸ್ಥಳ
ಸಮಯ ಬಿಡುಗಡೆಯತ್ತ ಸೂಚಿಸುತ್ತಿತ್ತು. ಬಿಡುಗಡೆಯ ನಂತರ, ಡೆಪ್ಲಾಯ್ನಿಂದ ಅಡಚಣೆಗೊಂಡ ಏಜೆಂಟ್ ತಿರುವುಗಳು ಮತ್ತೆ ಆರಂಭವಾಗಿ ತಮ್ಮ ಪ್ರತಿಲೇಖನಗಳನ್ನು ಮತ್ತೆ ಉಳಿಸುತ್ತವೆ, ಮತ್ತು ಆ ಹೆಚ್ಚುವರಿ ಕೆಲಸದ ಸ್ಫೋಟ ಮೆಮೊರಿ ಏರಿಕೆಗೆ ಸ್ಪಷ್ಟ ಕಾರಣದಂತೆ ಕಂಡಿತು.
ಆದ್ದರಿಂದ ಮೊದಲ ಬದಲಾವಣೆ API ಯ ಮಿತಿಯನ್ನು 384 MiB ಯಿಂದ 768 MiB ಗೆ ಏರಿಸಿತು. ಎರಡೂ ಸರ್ವರ್ಗಳಲ್ಲಿ ಅದೇ ದಿನ ನೇರವಾಗಿ ಅನ್ವಯಿಸಿದೆವು, ಮತ್ತು ಮುಂದಿನ ಡೆಪ್ಲಾಯ್ ಅದನ್ನು ಸದ್ದಿಲ್ಲದೆ 384 ಗೆ ಹಿಂತಿರುಗಿಸದಂತೆ ಡೆಪ್ಲಾಯ್ ಕಾನ್ಫಿಗರೇಶನ್ನಲ್ಲಿ ಬದ್ಧ ಮಾಡಿದೆವು. ಸರ್ವರ್ನಲ್ಲಿ ಕೈಯಿಂದ ಮಾಡಿದ ಪರಿಹಾರವನ್ನು ಮುಂದಿನ ಡೆಪ್ಲಾಯ್ ರದ್ದುಗೊಳಿಸಿದರೆ, ಅದೇ ಸ್ಥಗಿತ ಮರಳಿ ಬರುವ ಸಾಮಾನ್ಯ ದಾರಿ ಇದು.
ಹೆಚ್ಚು ಮೆಮೊರಿ ಸಮಂಜಸವಾದ ಸುರಕ್ಷತಾ ಅಂತರವಾಗಿತ್ತು. ಅದು ವಿವರಣೆಯಾಗಿರಲಿಲ್ಲ.
ನಿಜವಾದ ಕಾರಣ: ಒಂದು ವಿನಂತಿ, 71 MB
ನಂತರ ಅದೇ ದಿನ, ಉತ್ಪಾದನೆಯ ಹಳೆಯ ಮೆಮೊರಿ ಮಿತಿಯನ್ನು ಬಳಸಿ, ಒಂದು ಚಾಟ್ನ ಪ್ರತಿಯಲ್ಲಿ ಕ್ರ್ಯಾಶ್ ಅನ್ನು ಮರುಸೃಷ್ಟಿಸಿದೆವು. ಆ ಪ್ರತಿ ಡೆಪ್ಲಾಯ್ ಇಲ್ಲದೆಯೇ API ಅನ್ನು ಸ್ವತಃ ಕ್ರ್ಯಾಶ್ ಮಾಡಿತು.
ನೀವು ಒಂದು ಪ್ರಾಜೆಕ್ಟ್ ತೆರೆದಾಗ, ವೆಬ್ ಆ್ಯಪ್ ಆ ಚಾಟ್ನ ಇತಿಹಾಸಕ್ಕಾಗಿ API ಅನ್ನು ಕೇಳುತ್ತದೆ. ಎಂಡ್ಪಾಯಿಂಟ್ ಇತ್ತೀಚಿನ 30 ಸಂದೇಶಗಳನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಹಿಂತಿರುಗಿಸಿತು. ಹೆಚ್ಚಿನ ಚಾಟ್ಗಳಿಗೆ, 30 ಸಂದೇಶಗಳು ಚಿಕ್ಕದಾಗಿವೆ. ಈ ಚಾಟ್ಗೆ, ಇತ್ತೀಚಿನ 30 ಸಂದೇಶಗಳು ಡೇಟಾಬೇಸ್ನಲ್ಲಿ 53 MB ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ 71 MB ಆಗಿದ್ದವು. ಏಜೆಂಟ್ನ ಕೆಲವು ಉತ್ತರಗಳು ತಲಾ 4–10 MB ಇದ್ದವು, ಹೆಚ್ಚಾಗಿ ಉಪ-ಏಜೆಂಟ್ಗಳ ಪ್ರತಿಲೇಖನಗಳು: ಮುಖ್ಯ ಏಜೆಂಟ್ ಕಾರ್ಯದ ಒಂದು ಭಾಗವನ್ನು ಸಮಾನಾಂತರವಾಗಿ ಮಾಡಲು ಪ್ರಾರಂಭಿಸುವ ಸಹಾಯಕ ಏಜೆಂಟ್ಗಳು, ಅವುಗಳ ಸಂಪೂರ್ಣ ಕೆಲಸ ಉತ್ತರದೊಂದಿಗೆ ಉಳಿಸಲ್ಪಟ್ಟಿರುತ್ತದೆ.
ಆ ಒಂದು ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ನಿರ್ಮಿಸಲು API ಹೊಂದಿದ್ದಕ್ಕಿಂತ ಹೆಚ್ಚು ಹೀಪ್ ಬೇಕಾಯಿತು. ಮತ್ತು ಆ ಪ್ರಾಜೆಕ್ಟ್ ಅನ್ನು ತೆರೆಯುವ ಅಥವಾ ರಿಫ್ರೆಶ್ ಮಾಡುವ ಪ್ರತಿ ಸಲವೂ ವಿನಂತಿ ಮತ್ತೆ ಹೋಗುತ್ತಿತ್ತು. ಒಂದೇ ಚಾಟ್ ಅದು ಯಾವ ಸರ್ವರ್ಗೆ ಹೋದರೂ ಅದನ್ನು ಕೆಡವಬಲ್ಲದು, ಮತ್ತು ಪುಟವನ್ನು ಮರುಲೋಡ್ ಮಾಡಬಹುದಾದ್ದರಿಂದ, ಅದು ಎರಡನ್ನೂ ತಲುಪಬಹುದಿತ್ತು.
“30 ಸಂದೇಶಗಳು” ಗಾತ್ರದ ನಿಜವಾದ ಮಿತಿಯಾಗಿರಲಿಲ್ಲ. ಸಾಮಾನ್ಯ ಚಾಟ್ಗಳಿಗೆ ಚಿಕ್ಕದಾಗಿ ಇದ್ದ ಸಂಖ್ಯೆಯ ಮಿತಿಯಾಗಿತ್ತು.
ಪರಿಹಾರ: ಸಂಖ್ಯೆ ಮಾತ್ರವಲ್ಲ, ಗಾತ್ರದ ಆಧಾರದ ಪುಟಗಳು
ಈಗ ಇತಿಹಾಸದ ಒಂದು ಪುಟ 30 ಸಂದೇಶಗಳು ಅಥವಾ ಸುಮಾರು 4 MB ಯಷ್ಟು ಇರುತ್ತದೆ — ಯಾವುದು ಮೊದಲು ಬರುತ್ತದೆಯೋ ಅದು.
ಇದು ಎರಡು ಹಂತಗಳಲ್ಲಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ:
- ಮೊದಲು ಗಾತ್ರಗಳನ್ನು ಕೇಳಿ. API ಡೇಟಾಬೇಸ್ನಿಂದ ಇತ್ತೀಚಿನ ಸಂದೇಶಗಳ ID ಗಳು ಮತ್ತು ಸಂಗ್ರಹಿತ ಗಾತ್ರಗಳನ್ನು ವಿಷಯವಿಲ್ಲದೆ ಕೇಳುತ್ತದೆ. ಆ ಪ್ರಶ್ನೆ ಸಂದೇಶಗಳು ಎಷ್ಟೇ ದೊಡ್ಡದಾಗಿದ್ದರೂ ಅಗ್ಗವಾಗಿರುತ್ತದೆ.
- ಹೊಂದುವಷ್ಟನ್ನು ಮಾತ್ರ ಲೋಡ್ ಮಾಡಿ. ಹೊಸದರಿಂದ ಹಳೆಯದರ ಕಡೆಗೆ ಸಾಗುತ್ತಾ, ಮುಂದಿನ ಸಂದೇಶ ಪುಟವನ್ನು 4 MB ಮೀರಿಸುವವರೆಗೆ ಸಂದೇಶಗಳನ್ನು ಸೇರಿಸುತ್ತದೆ. ನಂತರ ಆ ಸಾಲುಗಳನ್ನು ಮಾತ್ರ ಪೂರ್ತಿಯಾಗಿ ಲೋಡ್ ಮಾಡಲಾಗುತ್ತದೆ.
ಇದನ್ನು ಸುರಕ್ಷಿತವಾಗಿಡುವ ಎರಡು ನಿಯಮಗಳಿವೆ:
- ಹೊಸ ಸಂದೇಶ ಯಾವಾಗಲೂ ಪುಟದಲ್ಲಿರುತ್ತದೆ, ಅದರ ಗಾತ್ರ ಎಷ್ಟೇ ಇರಲಿ. ಏನನ್ನೂ ಹಿಂತಿರುಗಿಸದ ಪುಟ ಚಾಟ್ ಅನ್ನು ಸಿಕ್ಕಿಹಾಕಿಕೊಳ್ಳುವಂತೆ ಮಾಡುತ್ತದೆ, ಹಿಂದಕ್ಕೆ ಸ್ಕ್ರೋಲ್ ಮಾಡಲು ಯಾವ ದಾರಿಯೂ ಇರುವುದಿಲ್ಲ.
- ಏನನ್ನೂ ಕತ್ತರಿಸುವುದಿಲ್ಲ. ಯಾವುದೇ ಸಂದೇಶವನ್ನು ಟ್ರಂಕೇಟ್ ಮಾಡುವುದಿಲ್ಲ ಅಥವಾ ಬಿಡುವುದಿಲ್ಲ. ಉಳಿದ ಚಾಟ್ ಹಳೆಯ ಸಂದೇಶಗಳಿಗೆ ಈಗಾಗಲೇ ಬಳಸಲಾಗುತ್ತಿದ್ದ “ಹಿಂದಿನ ಸಂದೇಶಗಳಿಗಾಗಿ ಮೇಲೆ ಸ್ಕ್ರೋಲ್ ಮಾಡಿ” ನಿಯಂತ್ರಣದ ಮೂಲಕ, ಒಂದೊಂದು ಪುಟವಾಗಿ ಲೋಡ್ ಆಗುತ್ತದೆ.
ಇದೇ ಆಕಾರದ ಇನ್ನೊಂದು ಸ್ಥಳವನ್ನೂ ಕಂಡೆವು. ನೀವು ಒಂದು ತಿರುವನ್ನು ನಿಲ್ಲಿಸಿದಾಗ, API ಕೊನೆಯ ಕೆಲವು ಉತ್ತರಗಳು ಖಾಲಿ ಇವೆಯೇ ಮತ್ತು ಶುಚಿಗೊಳಿಸಬೇಕೇ ಎಂದು ಪರಿಶೀಲಿಸುತ್ತದೆ. ಅದು ಎಂಟು ಪೂರ್ಣ ಸಂದೇಶಗಳನ್ನು ಲೋಡ್ ಮಾಡುವ ಮೂಲಕ ಮಾಡುತ್ತಿತ್ತು. ಬಹು-ಮೆಗಾಬೈಟ್ ಉತ್ತರಗಳ ಚಾಟ್ನಲ್ಲಿ, ಅದು ಚಿಕ್ಕ ರೂಪದಲ್ಲಿ ಅದೇ ಸಮಸ್ಯೆ. ಈಗ ವಿಷಯವನ್ನೇ ಲೋಡ್ ಮಾಡದೆ, ಡೇಟಾಬೇಸ್ಗೆ ಹೌದು-ಅಥವಾ-ಇಲ್ಲ ಪ್ರಶ್ನೆ ಕೇಳುತ್ತದೆ — ಈ ಸಂದೇಶದಲ್ಲಿ ಯಾವುದೇ ವಿಷಯವಿದೆಯೇ?
ನಾವು ಇದನ್ನು ಹೇಗೆ ಪರಿಶೀಲಿಸಿದೆವು
ಚಾಟ್ನ ಪ್ರತಿಯಲ್ಲಿ, ಹಳೆಯ 384 MiB ಮಿತಿಯೊಂದಿಗೆ ನಡೆಸಿ:
- ಮೊದಲ ಪುಟ 5 MB. ಮೊದಲು ಅದೇ ವಿನಂತಿ API ಅನ್ನು ಕೆಡವುತ್ತಿತ್ತು.
- ಒಮ್ಮೆಗೇ ಐದು ಬ್ರೌಸರ್ ಟ್ಯಾಬ್ಗಳಲ್ಲಿ ಚಾಟ್ ತೆರೆದಾಗ ಗರಿಷ್ಠ ಮೆಮೊರಿ 154 MB.
- ಇಡೀ ಚಾಟ್ ಮೂಲಕ ಹಿಂದಕ್ಕೆ ಸ್ಕ್ರೋಲ್ ಮಾಡಿದಾಗ, ಎಲ್ಲಾ 190 ಸಂದೇಶಗಳೂ ಒಮ್ಮೆ ಮಾತ್ರ, ಕ್ರಮದಲ್ಲಿ ಹಿಂತಿರುಗುತ್ತವೆ.
ಪುಟ ಆಯ್ಕೆ ತರ್ಕಕ್ಕೆ ಯುನಿಟ್ ಪರೀಕ್ಷೆಗಳೂ ಇವೆ, ಆ ಚಾಟ್ನ ಇತ್ತೀಚಿನ ಸಂದೇಶಗಳ ನಿಜವಾದ ಗಾತ್ರಗಳಿಂದ ನಿರ್ಮಿಸಿದ ಒಂದೂ ಸೇರಿದೆ. ಮೊದಲ ಪುಟ ಒಂದು ಸಂದೇಶವನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ, ಇನ್ನೂ ಇವೆ ಎಂದು ಹೇಳುತ್ತದೆ, ಮತ್ತು ಮುಂದಿನ ಪುಟ ಅದರ ನಂತರದಿಂದ ಆರಂಭವಾಗುತ್ತದೆ.
ನಾವು ಇದರಿಂದ ಕಲಿತದ್ದು
- ಸಂಖ್ಯೆ ಗಾತ್ರದ ಮಿತಿಯಲ್ಲ. ಅನಿಯಮಿತವಾಗಿ ಬೆಳೆಯಬಹುದಾದ ಯಾವುದರ “ಇತ್ತೀಚಿನ N” ಅನ್ನು ಹಿಂತಿರುಗಿಸುವ ಯಾವುದೇ ಎಂಡ್ಪಾಯಿಂಟ್ಗೆ ಬೈಟ್ ಬಜೆಟ್ ಕೂಡ ಬೇಕು. ಡೇಟಾ ಅಂತಿಮವಾಗಿ ಆ ಅಂತರವನ್ನು ಕಂಡುಹಿಡಿಯುತ್ತದೆ.
- ಸ್ಪಷ್ಟ ಶಂಕಿತ ಯಾವಾಗಲೂ ಕಾರಣವಾಗಿರುವುದಿಲ್ಲ. ಡೆಪ್ಲಾಯ್ ಹೆಚ್ಚುವರಿ ಕೆಲಸಕ್ಕೆ ನಿಜವಾದ ಪ್ರಚೋದಕವಾಗಿತ್ತು, ಮತ್ತು ಹೆಚ್ಚುವರಿ ಮೆಮೊರಿ ಯೋಗ್ಯವಾಗಿತ್ತು. ಆದರೆ ಕ್ರ್ಯಾಶ್ ಡೆಪ್ಲಾಯ್ ಇಲ್ಲದೆಯೇ ಮರುಸೃಷ್ಟಿಯಾಯಿತು, ಮತ್ತು ಅದನ್ನು ಮರುಸೃಷ್ಟಿಸದಿದ್ದರೆ ನಾವು ಮೆಮೊರಿ ಹೆಚ್ಚಳದಲ್ಲೇ ನಿಲ್ಲುತ್ತಿದ್ದೆವು.
- ಒಂದೇ ವಿನಂತಿ ಬಂದಾಗ ಎರಡು ಸರ್ವರ್ಗಳೂ ಒಟ್ಟಿಗೆ ವಿಫಲವಾಗುತ್ತವೆ. ಪುನರಾವರ್ತನೆ ಒಂದು ಸರ್ವರ್ ಸತ್ತರೆ ರಕ್ಷಿಸುತ್ತದೆ. ಅದು ತಲುಪುವ ಯಾವುದೇ ಸರ್ವರ್ ಅನ್ನು ಕೆಡವುವ ವಿನಂತಿಯಿಂದ ರಕ್ಷಿಸುವುದಿಲ್ಲ, ವಿಶೇಷವಾಗಿ ಬಳಕೆದಾರರು ರಿಫ್ರೆಶ್ ಮಾಡುವ ಮೂಲಕ ಸಹಜವಾಗಿ ಮರುಪ್ರಯತ್ನಿಸುವಂತಹದ್ದು.
- ಕಾನ್ಫಿಗ್ನಲ್ಲಿ ಸರಿಪಡಿಸಿ, ಕೇವಲ ಬಾಕ್ಸ್ನಲ್ಲಲ್ಲ. ಮೆಮೊರಿ ಹೆಚ್ಚಳವನ್ನು ಅದೇ ದಿನ ಡೆಪ್ಲಾಯ್ ಕಾನ್ಫಿಗರೇಶನ್ಗೆ ಸೇರಿಸಲಾಯಿತು, ಆದ್ದರಿಂದ ಮುಂದಿನ ಡೆಪ್ಲಾಯ್ ಅದನ್ನು ಉಳಿಸಿತು.
ಇದು ನಮ್ಮ ಏಜೆಂಟ್ನ ಔಟ್ಪುಟ್ ಸಂಬಂಧಿತ ಇತ್ತೀಚಿನ ಎರಡನೆಯ ಮೆಮೊರಿ ಕಥೆ. ಮೊದಲನೆಯದು 690 MB ಸ್ಟ್ರಿಂಗ್ಗಳನ್ನು ಸಾಲಿನಲ್ಲಿಟ್ಟ ಸ್ಥಿತಿ ಲೇಬಲ್. Mythex ನಲ್ಲಿ ಸಬ್-ಏಜೆಂಟ್ಗಳನ್ನು ಬಳಸಿದರೆ, ಅವು ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತವೆ ಎಂಬುದನ್ನು ಡಾಕ್ಸ್ ನಲ್ಲಿ ಓದಬಹುದು.