2015-07-07 9 views
5

मेरे पास एक वेब एप्लिकेशन है जो मैं शुरू कर रहा हूं। स्टार्टअप पर ठीक काम करता है लेकिन अगर मैं इसे छोड़ देता हूं (कहने के लिए, एक घंटा) और इसे किसी अन्य अनुरोध के साथ दबाएं तो क्वेरी लटकती है। मैंने प्रत्येक क्वेरी के बाद इसे बंद करने के बारे में सोचा और फिर एक नया कनेक्शन खोल दिया लेकिन दस्तावेज़ स्पष्ट रूप से कहते हैं, "डीबी को बंद करना दुर्लभ है, क्योंकि डीबी हैंडल लंबे समय तक रहने और कई गोरोटाइन के बीच साझा किया जाता है।" मैं क्या गलत कर रहा हूं?डेटाबेस का उपयोग नहीं किया जाता है अगर

package main 

import (
    "database/sql" 
    "log" 
    "net/http" 
    _ "github.com/lib/pq" 
) 

var Db *sql.DB 

func main() { 
    var err error 
    Db, err = sql.Open("postgres", "user=me password=openupitsme host=my.host.not.yours dbname=mydb sslmode=require") 
    if err != nil { 
    log.Fatal("Cannot connect to db: ", err) 
    } 
    http.HandleFunc("/page", myHandler) 
    http.ListenAndServe(":8080", nil) 
} 

func myHandler(w http.ResponseWriter, r *http.Request) { 
    log.Println("Handling Request....", r) 
    query := `SELECT pk FROM mytable LIMIT 1` 
    rows, err := Db.Query(query) 
    if err != nil { 
    log.Println(err) 
    } 
    defer rows.Close() 
    for rows.Next() { 
    var pk int64 
    if err := rows.Scan(&pk); err != nil { 
     log.Println(err) 
    } 
    log.Println(pk) 
    } 
    log.Println("Request Served...") 
} 

संपादित करें # 1:

2015-07-08 18:10:01 EDT [7710-1] [email protected] LOG: could not receive data from client: Connection reset by peer 
2015-07-08 18:20:01 EDT [7756-1] [email protected] LOG: could not receive data from client: Connection reset by peer 
+1

एक त्रुटि संदेश होना चाहिए। "क्वेरी लटकती है" पर्याप्त वर्णनात्मक नहीं है। – zerkms

+1

डीबी एक ही मशीन पर ऐप के रूप में स्थित है, या यह अलग है? क्या फ़ायरवॉल/एनएटी शामिल है (जहां निष्क्रियता के कारण राज्य का समय समाप्त हो सकता है। जब ऐप लटकता है तो नेटस्टैट अभी भी कनेक्शन को सक्रिय के रूप में दिखाता है? – Doon

+0

आप डीबी कहां चला रहे हैं? क्या यह उसकेोकू पर है? अगर उसका उपयोग नहीं किया जाता है तो हरोकू "सोता है" इसलिए अगली लाइव क्वेरी में समय लगेगा। साथ ही, कृपया ध्यान दें कि आपको प्रत्येक क्वेरी के लिए कनेक्शन खोलने और बंद करने की आवश्यकता नहीं है, लेकिन आपके पास अपने प्रोग्राम के अंत में एक करीबी बयान होना चाहिए। –

उत्तर

2

मैं इसी तरह के मुद्दों का अनुभव किया है: मेरे postgres शो लॉग इन करें। हमारे मामले में, समस्या क्लाइंट मशीन और डेटाबेस के बीच स्थित कनेक्शन ट्रैकिंग फ़ायरवॉल के कारण हुई थी।

ऐसे फ़ायरवॉल टीसीपी स्तर कनेक्शन का ट्रैक रखते हैं, और संसाधन उपयोग को सीमित करने के लिए, फिर उन कनेक्शनों का समय निकाल देगा जो उन्हें विस्तारित अवधि के लिए निष्क्रिय दिखाई देते हैं। इस मामले में हमने जो लक्षण देखा है, वे आपके समान ही थे: क्लाइंट के अंत में, कनेक्शन लटक रहा प्रतीत होता है, जबकि सर्वर के अंत में आप connection reset by peer देख सकते हैं।

यह सुनिश्चित करने का एक तरीका यह सुनिश्चित करना है कि TCP Keepalives सक्षम हैं, और रखरखाव अंतराल फ़ायरवॉल, राउटर, आदि के समय-समय से कम है जो आपके कनेक्शन समस्या का कारण बन रहा है। यह libpq कनेक्शन पैरामीटर keepalives, keepalives_idle, keepalives_interval और keepalives_count द्वारा नियंत्रित किया जाता है जिसे आप कनेक्शन स्ट्रिंग में सेट कर सकते हैं। इन पैरामीटर के विवरण के लिए manual देखें।

  • keepalive निर्धारित करता है कि रखरखाव कार्य सक्षम है या नहीं। यह 1 (सक्षम) पर डिफ़ॉल्ट है, इसलिए आपको शायद इसे निर्दिष्ट करने की आवश्यकता नहीं है।
  • keepalives_idle एक रखरखाव भेजने से पहले निष्क्रिय समय की मात्रा निर्धारित करता है। यदि आप इसे निर्दिष्ट नहीं करते हैं, तो यह ऑपरेटिंग सिस्टम के लिए डिफ़ॉल्ट पर डिफ़ॉल्ट होगा।

    लिनक्स सिस्टम में आप /proc/sys/net/ipv4/tcp_keepalive_time की जांच करके डिफ़ॉल्ट देख सकते हैं - मेरे सर्वर में यह 7200 सेकंड पर सेट है, जो आपके मामले में बहुत लंबा होगा, क्योंकि आपका अवलोकन यह है कि कनेक्शन ~ 1 घंटे के बाद गिरा दिया गया है।

    आप 2500 सेकंड कहने के लिए इसे सेट करने का प्रयास कर सकते हैं।

लिनक्स प्रलेखन परियोजना एक उपयोगी TCP Keepalive HOWTO दस्तावेज़ वर्णन करता है कि कैसे वे कुछ विस्तार से काम करती है।

ध्यान दें कि सभी ऑपरेटिंग सिस्टम टीसीपी रखरखाव का समर्थन नहीं करते हैं। , यदि यह आपके नियंत्रण में है

  1. फ़ायरवॉल/रूटर जो कनेक्शन गिरती है पुन: कॉन्फ़िगर इतना है कि यह इतना के लिए काम नहीं चलेगा: तुम यहाँ keepalives सक्षम कुछ अन्य विकल्प हैं करने में असमर्थ हैं, तो आप पर विचार करना चाहते हो सकता है Postgresql क्लाइंट कनेक्शन

  2. एक आवेदन स्तर पर, आप कुछ ट्रैफिक भेज सकते हैं जो डीबी हैंडल को सक्रिय रखेगा - उदाहरण के लिए प्रत्येक घंटे या तो SELECT 1; जैसे बयान भेजना। यदि आपका प्रोग्रामिंग वातावरण कनेक्शन कैशिंग प्रदान करता है (टिप्पणियों से मैं इसे इकट्ठा करता हूं) तो यह मुश्किल हो सकता है।

संबंधित मुद्दे