मृत कनेक्शनशिवाय जागे होणारे डेटाबेस
Mythex वरील प्रकाशित ॲप्स, आणि त्यांचे डेटाबेस, कोणीही वापरत नसताना झोपतात. ॲप जागे झाले तेव्हा त्याची पहिली विनंती 10–12 सेकंद धरून ठेवू शकत होते, कारण ते सर्व झोपेत असताना मृत झालेले database कनेक्शन पुन्हा वापरण्याचा प्रयत्न करत होते. आता आम्ही Spring Boot ॲप्सना झोपेनंतरही सुरक्षित असणाऱ्या database सेटिंग्ज देतो, आणि agent ला कोणत्याही stack चे ॲप्स त्याच पद्धतीने बनवण्यास सांगतो. होस्टिंग प्लॅटफॉर्मवर, जागे झाल्यानंतरची पहिली विनंती 12.7 सेकंदांवरून 2.3 सेकंदांवर आली.
ॲप्स आणि डेटाबेस का झोपतात
Mythex चे प्रकाशित ॲप काही निष्क्रिय मिनिटांनंतर थांबणाऱ्या मशीनवर चालते, आणि त्याचा डेटाबेस serverless Postgres आहे जो पाच निष्क्रिय मिनिटांनी झोपतो आणि पुढील विनंतीवर जागा होतो. त्यामुळे शांत ॲप स्वस्त राहते: डेटाबेस प्रत्यक्षात वापरलेल्या प्रमाणे तुमच्याकडून शुल्क आकारले जाते, आणि झोपलेले ॲप compute वर काहीही खर्च करत नाही. बिलिंगच्या बाजूवर आम्ही डेटाबेस त्यांनी प्रत्यक्षात वापरलेल्या प्रमाणात बिलिंग येथे लिहिले आहे.
अडचण अशी की दोघे वेगवेगळे झोपतात, आणि कनेक्शन म्हणजे काय याबद्दल त्यांचे एकमत नसते.
लक्षण: पहिली भेट मंद
बहुतेक server ॲप्स connection pool ठेवतात: मूठभर खुले database कनेक्शन तयार ठेवलेले, म्हणजे प्रत्येक विनंतीला नवे कनेक्शन उघडण्याचा खर्च द्यावा लागत नाही. सतत चालणाऱ्या ॲपसाठी हे योग्य डिझाइन आहे.
झोपेसह असे घडते:
- ॲप चालू आहे, त्याच्या pool मध्ये काही निष्क्रिय कनेक्शन्स आहेत.
- कोणी भेट देत नाही. ॲपचे मशीन थांबते — गोठलेले, pool जसाच्या तसा.
- Database झोपतो आणि प्रत्येक कनेक्शनचे त्याचे टोक सोडून देतो.
- एक visitor येतो. ॲप अगदी जसेच्या तसे जागे होते, तरीही त्याच्याकडे असलेली कनेक्शन्स database ला आता माहीत नसतात.
- Pool त्यापैकी एक कनेक्शन देतो. ते मृत आहे हे कळण्यासाठी त्याला ते प्रयत्न करून आणि वाट पाहून तपासावे लागते, मग त्यावर सोडून देण्यापूर्वी.
Spring Boot ॲपमध्ये, त्या मृत कनेक्शन्सची पडताळणी पहिल्या विनंतीला सुमारे 10 सेकंद अडवून ठेवत होती, मग "Connection is not available" ने ती अयशस्वी होत होती. Visitor ला साइट फक्त अडकलेली दिसत होती, आणि मग कदाचित एखादी error.
Spring ॲप्सना सर्वात जास्त त्रास का
Spring Boot हा लोकप्रिय Java framework आहे, आणि त्यात डीफॉल्टने HikariCP नावाचा connection pool वापरला जातो. Spring तो pool सेटिंग्जमधून कॉन्फिगर करू शकते, ज्यात किती निष्क्रिय कनेक्शन्स ठेवायची हेही येते.
पण Mythex प्रत्येक ॲपला त्याचा डेटाबेस postgresql://user:pass@host/db स्वरूपातील एकच DATABASE_URL म्हणून देते. Spring ते स्वरूप थेट वाचू शकत नाही. त्यामुळे Mythex वर बनलेली Spring ॲप्स त्या URL चा अर्थ लावून कोडमध्ये स्वतःचा pool बनवत होती — आणि हाताने बनवलेला pool Spring च्या सर्व spring.datasource.* सेटिंग्जकडे दुर्लक्ष करतो. कोणाला योग्य pool सेटिंग्ज माहीत असल्या तरी त्या लागू होण्यासारखे कोणतेही ठिकाण नव्हते.
उपाय, भाग 1: Spring वापरू शकेल अशा सेटिंग्ज
एखाद्या प्रोजेक्टला डेटाबेस असेल तर आता त्याला Spring थेट वाचू शकेल अशा environment variables देखील मिळतात:
SPRING_DATASOURCE_URL,SPRING_DATASOURCE_USERNAMEआणिSPRING_DATASOURCE_PASSWORD,DATABASE_URLवरून रूपांतरित (URL मध्ये वेगळे नमूद नसल्यास SSL आवश्यक).- झोपेनंतरही टिकणाऱ्या pool सेटिंग्ज:
| सेटिंग | मूल्य | का |
|---|---|---|
| किमान निष्क्रिय कनेक्शन्स | 0 | विनंत्यांमध्ये काहीही खुले न ठेवणे, त्यामुळे मृत होण्यासारखे काही नसते |
| निष्क्रिय timeout | 30 सेकंद | न वापरलेली कनेक्शन्स लवकर बंद करणे |
| कमाल आयुष्य | 2 मिनिटे | कोणतेही कनेक्शन जुने होण्यापूर्वी ते निवृत्त करणे |
| कनेक्शन timeout | 5 सेकंद | डेटाबेस उत्तर देण्यास मंद असल्यास विनंती जास्त वेळ न अडवणे |
कोणतेही निष्क्रिय कनेक्शन खुले न ठेवल्यामुळे, जागा झालेले ॲप मृत कनेक्शन्समधून जाण्याऐवजी एक नवीन कनेक्शन उघडते.
ही variables उपस्थित असताना Spring स्वतः pool कॉन्फिगर करते, आणि सेटिंग्ज लागू होतात. प्रोजेक्टने स्वतः काही सेट केले असेल तर ते नेहमी जिंकते; आम्ही फक्त जे गहाळ आहे तेवढेच भरतो. Spring नसलेली ॲप्स ही variables दुर्लक्षित करतात.
जवळजवळ काहीच न करणारा तपशील
Spring environment variables ना आपल्या सेटिंग्जमध्ये मॅप करते तो नियम सहज चुकतो. minimum-idle सेटिंग SPRING_DATASOURCE_HIKARI_MINIMUMIDLE असे लिहावे लागते — dashes गाळून, शब्द एकत्र जोडून. SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE असे लिहिले, जे अधिक नैसर्गिक वाटते, ते वेगळ्या, अस्तित्वात नसलेल्या सेटिंगशी (minimum.idle) जोडले जाते आणि शांतपणे दुर्लक्षित होते.
अशी चूक प्रत्येक review मधून जाते आणि production मध्ये काहीही करत नाही. म्हणून एक चाचणी दोन्ही तपासते: मूल्ये सेट आहेत आणि कोणतीही variable underscore-वेगळे स्वरूप वापरत नाही.
उपाय, भाग 2: इतर प्रत्येक stack
Spring हा pool असलेला एकमेव framework नाही, आणि आम्ही प्रत्येक भाषेतील प्रत्येक library पूर्व-कॉन्फिगर करू शकत नाही. म्हणून ॲप लिहिणाऱ्या Mythex agent ला आता कोणत्याही stack साठी एक स्थायी सूचना मिळते: प्रकाशित ॲप्स आणि त्यांचे डेटाबेस निष्क्रिय असताना झोपतात, त्यामुळे खुले ठेवलेले कनेक्शन पुढील विनंतीला मृत असू शकते. त्याने:
- कोणतेही निष्क्रिय database कनेक्शन खुले ठेवू नये, किंवा वापरण्यापूर्वी प्रत्येकाची तपासणी करावी,
- कनेक्शन error वर एकदा पुन्हा प्रयत्न करावा, आणि
DATABASE_URLचा अर्थ लावून स्वतःचा pool बनवण्याऐवजी environment मध्ये प्लॅटफॉर्म देत असलेल्या database सेटिंग्ज वापराव्यात.
शेवटचा मुद्दा भाग 1 शी जोडतो: प्रदान केलेल्या सेटिंग्जवर बनलेले ॲप झोपेसाठी सुरक्षित configuration आपोआप घेते.
निकाल
ज्या होस्टिंग प्लॅटफॉर्मवर आम्ही प्रकाशित ॲप्स चालवतो, तिथे मोजल्यावर जागे झाल्यानंतरची पहिली विनंती 12.7 सेकंदांवरून 2.3 सेकंदांवर आली.
त्यातून आम्ही काय शिकलो
- झोपणारा प्रत्येक थर काय टिकते यावर सहमत असला पाहिजे. गोठलेले ॲप आणि झोपलेला डेटाबेस दोघांनीही वाजवी निवड केली. एकत्र, ॲप अशा स्थितीसह जागे झाले जी आता खरी नव्हती.
- नेहमी-चालू सर्व्हरसाठी बनवलेले डीफॉल्ट शून्यावर स्केल होणाऱ्या ॲप्सना बसत नाहीत. कनेक्शन्स उबदार ठेवणे चांगली कल्पना आहे, जोपर्यंत त्यांच्या भोवतीचे सर्व थंड होत नाही.
- फ्रेमवर्क्सना त्यांचा डेटा त्यांच्या स्वतःच्या स्वरूपात द्या. एक URL आमच्यासाठी साधे होते, पण प्रत्येक Spring ॲपला स्वतःचा pool हाताने बनवायला भाग पाडत होते जो स्वतःच्या configuration कडे दुर्लक्ष करत होता.
- सेटिंग फ्रेमवर्क वाचते त्या स्पेलिंगमध्ये आहे का ते तपासा. योग्य मूल्य चुकीच्या नावाखाली शांतपणे काहीच करत नाही.
Mythex वर डेटाबेस कसे काम करतात याबद्दल अधिक माहितीसाठी database docs आणि आमचे Postgres म्हणजे काय हे स्पष्टीकरण पहा.