2015-10-18 41 views
0

我在go程序中對api進行大量Web調用,並將結果存儲在數據庫中(使用mgo)。 api調用是在單獨的例程中完成的。在其他例程中,我將信息從數據庫中提取出來並進行處理,然後再更新數據庫。當數據放回時,將設置一個標誌,以便知道該數據已經過後處理,因此當程序要求數據庫提供另一個條目以便後處理時,數據庫將返回一個標誌爲complete的標誌設置爲。當標誌設置爲true時,關閉例行程序:wg.done()go(golang)對例程的mongodb查詢會產生巨大的堆棧跟蹤(使用mgo)

一切都很好,我有很多的打印輸出的告訴我的程序是怎樣了,但朝其運行結束時,我得到一個包含很多相同的一個巨大的堆棧跟蹤:

夠程56731 [sleep]:time.Sleep(0x12a05f200) /usr/local/Cellar/go/1.5/libexec/src/runtime/time.go:59+ 0xf9 gopkg.in/mgo%2ev2.(*mongoServer).pinger (0xc82601b420,0x1) /Users/alex/go/src/gopkg.in/mgo.v2/server.go:295+ 0x1b4由 創建gopkg.in/mgo%2ev2.newServer /Users/alex/go/src/gopkg.in/mgo.v2/server.go:88 + 0x162

夠程56698 [睡眠]:time.Sleep(0x12a05f200) /usr/local/Cellar/go/1.5/libexec/src/runtime/time.go:59 + 0xf9 gopkg.in/mgo%2ev2(。 * mongoServer).pinger(0xc82601bce0,0x1) /Users/alex/go/src/gopkg.in/mgo.v2/server.go:295+ 0x1b4由 創建gopkg.in/mgo%2ev2.newServer /Users /alex/go/src/gopkg.in/mgo.v2/server.go:88 + 0x162

夠程56699 [睡眠]:time.Sleep(0x1dcd6500) /usr/local/Cellar/go/1.5/ libexec/src/runtime/time.go:59 + 0xf9 gopkg.in/mgo%2ev2.(*mongoCluster).syncServersLoop(0xc8256425a0) /Users/alex/go/src/gopkg.in/mgo.v2/cluster 。去:353 + 0x2b1創建由 gopkg.in/mgo%2ev2.newCluster /Users/alex/go/src/gopkg.in/mgo.v2/cluster.go:73 +量0x1A0

夠程56738 [睡眠]:time.Sleep(0x12a05f200) /usr/local/Cellar/go/1.5/libexec/src/runtime/time.go:59+ 0xf9 gopkg.in/mgo%2ev2.(*mongoServer).pinger(0xc82606fa40) ,0x1) /Users/alex/go/src/gopkg.in/mgo.v2/server.go:295+ 0x1b4由 創建gopkg.in/mgo%2ev2.newServer /Users/alex/go/src/gopkg.in/mgo.v2/server.go:88+0x162

有一件事是所有thos e下面,這是堆棧跟蹤上面唯一不同的輸出(上面只是一個例子,我的終端不能回滾到開頭有這麼多)

goroutine 57201 [ IO等待]:net.runtime_pollWait(0xedb6f0,0x72, 0xc82000a2c0) /usr/local/Cellar/go/1.5/libexec/src/runtime/netpoll.go:157+ 0x60 net。(* pollDesc).Wait( 0xc827b0e5a0,0x72,0x0,0x0) /usr/local/Cellar/go/1.5/libexec/src/net/fd_poll_runtime.go:73+ 0x3a net。(* pollDesc).WaitRead(0xc827b0e5a0,0x0,0x0) /usr/local/Cellar/go/1.5/libexec/src/net/fd_poll_runtime.go:78+ 0x36 net。(* netFD).Read(0xc827b0e540,0x c828d61000,0x1000,0x1000,0x0, 0x754050,0xc82000a2c0) /usr/local/Cellar/go/1.5/libexec/src/net/fd_unix。(* conn).Read(0xc8260eac38,0xc828d61000,0x1000,0x1000,0x0,0x0, 0x0)/usr/local/Cellar/go/1.5/libexec/src/net/net.go(232)0x23a net。(* conn) :172 + 0xe4 淨/ http.noteEOFReader.Read(0x7960c0,0xc8260eac38,0xc82751fd38, 0xc828d61000,0x1000的,0x1000的,0xc82644dc20,爲0x0,爲0x0) /usr/local/Cellar/go/1.5/libexec/src/net/ http/transport.go:1370 + 0x67 net/http。(* noteEOFReader).Read(0xc826116e60,0xc828d61000,0x1000, 0x1000,0xc827d1a770,0x0,0x0):126 + 0xd0 bufio。(* Reader).fill 0xc82644d4a0) /usr/local/Cellar/go/1.5/libexec/src/bufio/bufio.go:97 + 0x1e9 BUFIO。(*閱讀器).Peek(0xc82644d4a0,爲0x1,爲0x0,爲0x0,爲0x0,爲0x0,爲0x0 ) /usr/local/Cellar/go/1.5/libexec/sr (* persistConn).readLoop(0xc82751fce0) /usr/local/Cellar/go/1.5/libexec/src/net/http/transport.go:876 + 0xf7 通過網/ HTTP創建的。(*運輸).dialConn /usr/local/Cellar/go/1.5/libexec/src/net/http/transport.go:685 + 0xc78

我努力弄清楚它告訴我什麼,是否鎖定寫入數據庫,例程是否關閉以及是否超時,我不知道。 我使用去1.5順便說一句。

如何解釋上述任何幫助將是偉大的。

與數據庫會談代碼如下:

func (l *Ledger) addRaceToDatabase(race Race) { //true if added, 

false if existed 
    session, err := mgo.Dial("127.0.0.1") 
    if err != nil { 
    panic(err) 
    } 

    defer session.Close() 

    session.SetMode(mgo.Monotonic, true) 

    c := session.DB("collection").C("races") 

    // Index 
    index := mgo.Index{ 
    Key:  []string{"id"}, 
    Unique:  true, 
    DropDups: true, 
    Background: true, 
    Sparse:  true, 
    } 

    err = c.EnsureIndex(index) 
    if err != nil { 
    panic(err) 
    } 

    result := Race{} 
    //if the race exists, don't add it to the database 
    err = c.Find(bson.M{"id": race.ID}).One(&result) 
    if err != nil { 
    //if there is an error there wasn't an entry so add this to the database 
    err = c.Insert(race) 
    if err != nil { 
     panic(err) 
    } 
    } else { 
    //if it does find an entry, it will print it 
    fmt.Println("FOUND: ", result.ID) 
    } 
} 
+2

你需要上傳你的數據庫代碼,以幫助調試這個效率 - 特別是圍繞你如何使用goroutines。 – elithrar

+0

編輯問題以包含與數據庫通信的代碼。 Thx – amlwwalker

回答

0

它看起來像引述邏輯在每次需要用它做什麼的時候,這是不舉行持續適當的方式撥打的MongoDB數據庫在HTTP服務器中的通信。

每次您在Dial一個MongoDB服務器(或副本集或mongos)時,都會啓動一些後臺活動,以保持集羣拓撲在內存中保持最新狀態並保持連接池健全(請注意,在單個Dial調用將共享單個連接池之後創建的所有會話)。

每次想要與數據庫交談時調用Dial意味着所有的邏輯都對每個撥號都是獨立的,並且該後臺活動可能需要片刻才能在最後一個會話關閉後關閉。

因此,即使它能夠工作,但效率非常低,因爲它必須重新學習使用的拓撲結構,它無法使用來自現有池的連接,還會產生不必要的背景流失,這正是您觀察的內容你的回溯。

有關如何更好地保持在這一背景下,會議的一些想法,請參閱此主題:

+0

是啊,我意識到,我非常懶惰,並複製粘貼代碼,以確保它的工作。我打算清理數據庫連接,但是我不認爲它會改變爲什麼我會得到堆棧跟蹤? – amlwwalker

+0

我提供了上面粘貼的代碼中問題的詳細信息。你沒有使用你粘貼的代碼,或者你不同意這是問題嗎?如果你不同意,它應該比「我不認爲」更好。 –

+0

您的回覆看起來好像您在評論最佳做法和效率,而不是直接談論爲什麼我正在體驗堆棧跟蹤。我會整理它,以便它不會每次都連接和斷開連接 - 這是一個POC而不是「完成的代碼」 – amlwwalker