व्यस्त प्रक्रिया को डिबग करना
कभी-कभी हम php start.php status कमांड के माध्यम से busy स्थिति में प्रक्रियाओं को देख सकते हैं, जिसका अर्थ है कि संबंधित प्रक्रिया व्यवसाय को संभाल रही है। सामान्य स्थिति में, व्यवसाय को पूरा करने के बाद संबंधित प्रक्रिया idle स्थिति में वापस आ जाएगी। आमतौर पर इससे कोई समस्या नहीं होती है। लेकिन यदि यह लगातार busy स्थिति में है और idle स्थिति में वापस नहीं लौट रही है, तो इसका मतलब है कि प्रक्रिया के अंदर का व्यवसाय किसी अवरोध या अनंत लूप में है। इसे निम्नलिखित तरीकों से स्थानांतरित किया जा सकता है।
strace+lsof कमांड का उपयोग करके स्थानांतरण
1、status में busy प्रक्रिया का pid ढूंढें
php start.php status चलाने के बाद निम्नलिखित दिखाई देता है

चित्र में busy प्रक्रियाओं का pid है 11725 और 11748
2、strace प्रक्रिया को ट्रैक करें
एक प्रक्रिया pid का चयन करें (यहां 11725 चुनते हैं), strace -ttp 11725 चलाएँ और निम्नलिखित दिखाई देता है

यह देखा जा सकता है कि प्रक्रिया निरंतर poll([{fd=16, events=.... सिस्टम कॉल में लूप कर रही है, यह fd के लिए 16 के डिस्क्रिप्टर के पढ़ने की घटना की प्रतीक्षा कर रही है, अर्थात्, यह इस डिस्क्रिप्टर से डेटा लौटने की प्रतीक्षा कर रही है।
यदि कोई सिस्टम कॉल नहीं दिखाई दे रहा है, तो वर्तमान टर्मिनल को बनाए रखते हुए, एक नया टर्मिनल खोलें, kill -SIGALRM 11725 चलाएँ (प्रक्रिया को एक अलार्म सिग्नल भेजें), फिर देखें कि क्या strace के टर्मिनल पर कोई प्रतिक्रिया है, क्या किसी सिस्टम कॉल पर अवरोध हो रहा है। यदि अभी भी कोई सिस्टम कॉल नहीं दिखाई दे रहा है, तो यह दर्शाता है कि कार्यक्रम संभवतः व्यवसाय की मृत लूप में है। इस स्थिति में, पृष्ठ के निचले भाग में दी गई अन्य कारणों को देखें जो प्रक्रिया को लंबे समय तक व्यस्त रखते हैं, जो कि दूसरी आइटम को हल करें।
यदि सिस्टम epoll_wait या select सिस्टम कॉल पर अवरुद्ध है, तो यह सामान्य स्थिति है, इसका अर्थ है कि प्रक्रिया पहले से ही idle स्थिति में है।
3、lsof प्रक्रिया डिस्क्रिप्टर को देखें
lsof -nPp 11725 चलाने पर निम्नलिखित दिखाई देता है

डिस्क्रिप्टर 16 का संबंध 16u के रिकॉर्ड (अंतिम पंक्ति) से है, जिसमें fd=16 का डिस्क्रिप्टर एक tcp कनेक्शन है, दूरस्थ पता 101.37.136.135:80 है, इसका मतलब है कि प्रक्रिया एक HTTP संसाधन को एक्सेस कर रही है, लूप poll([{fd=16, events=.... हमेशा HTTP सर्वर से डेटा लौटने की प्रतीक्षा कर रहा है, यह समझाता है कि क्यों प्रक्रिया busy स्थिति में है।
हल:
अब जब हमें पता चल गया है कि प्रक्रिया कहाँ अवरुद्ध है, तो अगली बात इसे हल करना आसान है, जैसे ऊपर स्थानांतरण के माध्यम से पता किया गया है, व्यवसाय curl को कॉल कर रहा है और संबंधित URL लंबे समय से डेटा वापस नहीं कर रहा है, जिससे प्रक्रिया हमेशा प्रतीक्षा में है। इस स्थिति में, हम URL प्रदाता से संपर्क करके इस URL के धीमी प्रतिक्रिया का कारण ढूंढ सकते हैं, साथ ही curl कॉल करते समय टाइमआउट पैरामीटर जोड़ सकते हैं, जैसे 2 सेकंड में प्रतिक्रिया नहीं आने पर टाइमआउट, जिससे लंबे समय तक अवरोध समाप्त हो सके (इससे प्रक्रिया संभवतः लगभग 2 सेकंड के लिए busy स्थिति में हो सकती है)।
प्रक्रियाओं के लंबे समय तक व्यस्त रहने के अन्य कारण
प्रक्रिया अवरुद्ध होने के अलावा, जो कि प्रक्रिया को busy में रख सकता है, निम्नलिखित अन्य कारण भी प्रक्रियाओं को busy स्थिति में रख सकते हैं।
1、व्यवसाय में घातक त्रुटियाँ जो प्रक्रियाओं को निरंतर बाहर निकलने का कारण बनती हैं
फेनोमेना: इस स्थिति में, हम देख सकते हैं कि सिस्टम लोड अपेक्षाकृत उच्च है, status में load average 1 या उससे अधिक है। हम देख सकते हैं कि प्रक्रिया की exit_count संख्या बहुत उच्च है और निरंतर बढ़ती जा रही है।
हल: डिबग मोड में चलाएँ (php start.php start -d के बिना) workerman पर व्यवसाय की त्रुटियों को देखें और त्रुटियों को हल करें।
2、कोड में अनंत मृत लूप
फेनोमेना: top में देखा जा सकता है कि व्यस्त प्रक्रिया CPU का बहुत अधिक उपयोग कर रही है और strace -ttp pid कमांड कोई सिस्टम कॉल जानकारी प्रिंट नहीं कर रही है।
हल: gdb और php सोर्स कोड का उपयोग करके स्थिति का पता करने के लिए नियो की लेख को देखें, चरण का सारांश इस प्रकार है:
php -vका उपयोग करके संस्करण देखें- संबंधित php संस्करण का सोर्स कोड डाउनलोड करें
gdb --pid=busy प्रक्रिया का pidsource php सोर्स पथ/.gdbinitzbacktraceकॉल स्टैक प्रिंट करता है
अंतिम चरण में, आप देख सकते हैं कि php कोड वर्तमान में जिस कॉल स्टैक को निष्पादित कर रहा है वह मृत लूप का स्थान है।
ध्यान दें: यदिzbacktraceकॉल स्टैक को प्रिंट नहीं करता है, तो संभव है कि आपके php को संकलित करते समय-gपैरामीटर शामिल नहीं था, जिसके लिए php को फिर से संकलित करें और फिर workerman को फिर से चालू करें।
3、अनंत टाइमर जोड़ना
व्यवसाय का कोड निरंतर टाइमर जोड़ता है और उन्हें हटाता नहीं है, जिससे प्रक्रिया में टाइमर की संख्या बढ़ती जाती है और अंततः प्रक्रिया अनंत रूप से टाइमर चला रही होती है। उदाहरण के लिए, निम्नलिखित कोड:
$worker = new Worker;
$worker->onConnect = function($con){
Timer::add(10, function(){});
};
Worker::runAll();
उपरोक्त कोड तब एक टाइमर जोड़ देगा जब कोई क्लाइंट कनेक्ट होता है, लेकिन पूरे व्यवसाय के कोड में टाइमर को हटाने की कोई लॉजिक नहीं है, इस प्रकार समय के साथ, प्रक्रिया में टाइमर बढ़ता रहेगा, अंततः प्रक्रिया अनंत रूप से टाइमर चलाने का कारण बनती है।
सही कोड:
$worker = new Worker;
$worker->onConnect = function($con){
$con->timer_id = Timer::add(10, function(){});
};
$worker->onClose = function($con){
Timer::del($con->timer_id);
};
Worker::runAll();