globalsign / mgo

The MongoDB driver for Go
Other
1.97k stars 232 forks source link

how to ensure the sockets in unusedSockets available #369

Open NeoyeElf opened 5 years ago

NeoyeElf commented 5 years ago

What version of MongoDB are you using (mongod --version)?

3.4

What version of Go are you using (go version)?

1.11

What did you do?

my program uses the mgo to connect to a mongo shard cluster. When the concurrent requests increase rapidly, some of my mongo query would return err like "insert err:write results unavailable from ${ip} :: caused by :: Location11002: socket exception [CONNECT_ERROR]".

I think the socket occurs some network connection error, so I use the following code to get a new session(I.e. socket)

session.Close()
globalSession.Copy()

The problem seems to be solved.

recently, I have dig into some of the source code and have some questions for the following code:

// Release decrements a socket reference. The socket will be
// recycled once its released as many times as it's been acquired.
func (socket *mongoSocket) Release() {
    socket.Lock()
    if socket.references == 0 {
        panic("socket.Release() with references == 0")
    }
    socket.references--
    stats.socketRefs(-1)
    if socket.references == 0 {
        stats.socketsInUse(-1)
        server := socket.server
        closeAfterIdle := socket.closeAfterIdle
        socket.Unlock()
        socket.LogoutAll()
        if closeAfterIdle {
            socket.Close()
        } else if server != nil {
            // If the socket is dead server is nil.
            server.RecycleSocket(socket)
        }
    } else {
        socket.Unlock()
    }
} 

Here is my question: if a socket that has some network connection error(like I said above) is put back to the unusedSockets slice by calling the session.Close(), which calls socket.Release(), will I encounter the error again when I use the session acquire the socket from unusedSockets? Have not seen any code to ensure the socket available(or I just missed)

Thks!