Get the App
SLTechnology News&Howtos  ›  Development  › 

How to implement the Mongodb Agent

Shulou Source: shulou.com Published: 2022-06-01 08:13:14 10月04日 Update

This article mainly introduces the relevant knowledge of "how to realize the Mongodb agent program". The editor shows you the operation process through the actual case, the operation method is simple and fast, and the practicality is strong. I hope this article "how to implement the Mongodb agent program" can help you solve the problem.

According to the usual style, let's first sort out the project directory structure as follows:

| | _ _ bin/ # is used to store binary files generated after compilation |

| | _ _ config/ # is used to store configuration files |

| | _ _ connection/ # stores connection-related files |

| | _ _ proxy.go # proxy component |

| | _ _ pool.go # connection pool component |

| | _ _ repl_set.go # replication set component |

| | _ _ conn.go # Connect object components |

| | _ _ internal/ # stores files related to mongo internal protocol |

| | _ _ auth.go # handshake authentication component |

| | _ _ protocol.go # Protocol parsing component |

| | _ _ request.go # request to rewrite the component |

| | _ _ response.go # response rewriting component |

| | _ _ statistics/ # component for reporting statistics of storage metrics |

| | _ _ test/ # folder where various language-driven test codes are stored |

| | _ _ utils/ # tool function folder |

| | _ _ glide.yaml # depends on the package configuration file |

| | _ _ main.go # entry file |

Proxy implementation

The simplest proxy implementation routines look like this:

/ / main.go

Func main () {

/ / pass in configuration parameters to instantiate a proxy object

P: = NewProxy (conf)

/ / get stuck and accept client requests in a loop

P.LoopAccept ()

}

Next, let's implement the NewProxy and LoopAccept methods:

/ / connection/proxy.go

Type Proxy struct {

Sync.RWMutex

Listener net.Listener

WritePool, readPool * pool

}

Func NewProxy (conf config.UserConf) * Proxy {

/ / start listening on the local port

Listener, err: = net.Listen ("tcp", ":" + conf.GetString ("port"))

If err! = nil {

Log.Fatalln (err)

}

P: = & Proxy {

Listener: listener

}

/ / instantiate connection pooling

P.readPool, p.writePool, err = newPool (p)

If err! = nil {

Panic (err)

}

Return p

}

Func (p * Proxy) LoopAccept () {

For {

Client, err: = p.listener.Accept ()

Go func (c net.Conn) {

Defer c.Close ()

/ / A connection shares one Reader object in multiple messageHandler

Cr: = bufio.NewReader (c)

/ / because a connection may perform multiple read or write operations

For {

/ / proxy the client request to the server, and the server responds to the proxy back to the client

/ / rewrite the request or response at the same time

Err: = p.messageHandler (cr, c)

If err! = nil {

/ / whenever an error occurs, execute defer c.Close () above to close the connection

Return

}

}

} (client)

}

}

Next, let's implement the core logic messageHandler:

/ / connection/proxy.go

Func (p * Proxy) messageHandler (cr * bufio.Reader, c net.Conn) error {

/ / A pair of request messages are parsed

Req, err: = internal.Decode (clientReader)

If err! = nil {

Return errors.New ("decode error")

}

/ / send the client request to the database server

Res, err: = p.clientToServer (req)

If err! = nil {

Return errors.New ("request error")

}

/ / return the database server response to the client

Return res.WriteTo (c)

}

Func (p * Proxy) clientToServer (req * internal.Message) (* internal.Message, error) {

Var server net.Conn

/ / if it is a read operation, remove the connection from the read pool

If req.IsReadOp () {

Host: = req.GetHost ()

/ / some read operations need to be sent to the specified read library, so you need to send host to get the specified read library connection.

Server = p.readPool.Acquire (host)

/ / conversely, the write operation removes the connection from the write pool

} else {

/ / since there is only one write library, there is no need to pass host parameters

Server = p.writePool.Acquire ()

}

/ / send the client request to the database server

Err: = req.WriteTo (server)

If err! = nil {

Return nil, err

}

/ / get the response of the parsing database server

Res, err: = internal.Decode (bufio.NewReader (server))

Return res, err

}

The general logic is that the client sends the request to the server through the agent, and the server responds back to the client through the agent.

-request-request-

| |-> | |-> | |

| | client | | proxy | | repl_set |

| | |

Tags: Agents clients clients files components services data databases servers programs objects methods knowledge logic configuration code parameters instances that is quantity Apple Docker Huawei Linux macOS MariaDB Microsoft MySQL NVidia OPPO Reno Apple vpn macOS OPPO Reno MariaDB