In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "the trampling analysis of golang fasthttp". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "the trampling analysis of golang fasthttp".
A simple system with the following structure:
Our service An accepts an external http request and then forwards the request to service B through golang's fasthttp. The process is very simple. After running online for a period of time, it is found that Service B no longer receives any requests at all. Check the log of Service An and find a large number of errors as follows
From the point of view of the error, it is because the connection is full. Enter the container of Service A (both Service An and Service B are started through docker), and check through netstat-anlp to find that there are a large number of tpc connections in ESTABLISH. We use the way of long connection, at this time we are very confused: 1. Fasthttp can reuse connections, why there are so many TCP connections, 2. Why can't these connections be used? what is the reason for the above exception?
Starting from the fasthttpclient source code, we call request forwarding using the
F.Client.DoTimeout (req, resp, f.ExecTimeout), where f.Client is a fasthttp.HostClient,f.ExecTimeout setting is 5s.
Trace the code until this method in client.go
Func (c * HostClient) doNonNilReqResp (req * Request, resp * Response) (bool, error) {if req = = nil {panic ("BUG: req cannot be nil")} if resp = = nil {panic ("BUG: resp cannot be nil")} atomic.StoreUint32 (& c.lastUseTime, uint32 (time.Now (). Unix ()-startTimeUnix)) / / Free up resources occupied by response before sending the request / / so the GC may reclaim these resources (e.g. Response body). Resp.Reset () / / If we detected a redirect to another schema if req.schemaUpdate {c.IsTLS = bytes.Equal (req.URI (). Scheme (), strHTTPS) c.Addr = addMissingPort (string (req.Host ()), c.IsTLS) c.addrIdx = 0 c.addrs = nil req.schemaUpdate = false req.SetConnectionClose ()} cc Err: = c.acquireConn () if err! = nil {return false, err} conn: = cc.c resp.parseNetConn (conn) if c.WriteTimeout > 0 {/ / Set Deadline every time, since golang has fixed the performance issue / / See https://github.com/golang/go/issues/15133#issuecomment-271571395 for details currentTime: = time.Now () if err = conn.SetWriteDeadline (currentTime.Add (c.WriteTimeout)) Err! = nil {c.closeConn (cc) return true Err}} resetConnection: = false if c.MaxConnDuration > 0 & & time.Since (cc.createdTime) > c.MaxConnDuration & &! req.ConnectionClose () {req.SetConnectionClose () resetConnection = true} userAgentOld: = req.Header.UserAgent () if len (userAgentOld) = 0 {req.Header.userAgent = c.getClientName ()} bw: = c.acquireWriter (conn) err = req.Write (bw) if resetConnection {req.Header.ResetConnectionClose ()} if err = = nil {err = bw.Flush ()} if err! = nil {c.releaseWriter (bw) c.closeConn (cc) return true Err} c.releaseWriter (bw) if c.ReadTimeout > 0 {/ / Set Deadline every time, since golang has fixed the performance issue / / See https://github.com/golang/go/issues/15133#issuecomment-271571395 for details currentTime: = time.Now () if err = conn.SetReadDeadline (currentTime.Add (c.ReadTimeout)) Err! = nil {c.closeConn (cc) return true, err}} if! req.Header.IsGet () & & req.Header.IsHead () {resp.SkipBody = true} if c.DisableHeaderNamesNormalizing {resp.Header.DisableNormalizing ()} br: = c.acquireReader (conn) if err = resp.ReadLimitBody (br, c.MaxResponseBodySize) Err! = nil {c.releaseReader (br) c.closeConn (cc) / / Don't retry in case of ErrBodyTooLarge since we will just get the same again. Retry: = err! = ErrBodyTooLarge return retry, err} c.releaseReader (br) if resetConnection | | req.ConnectionClose () | | resp.ConnectionClose () {c.closeConn (cc)} else {c.releaseConn (cc)} return false, err}
Notice the method c.acquireConn (), which gets the connection from the connection pool and creates a new connection if no connection is available. This method is implemented as follows
Func (c * HostClient) acquireConn () (* clientConn, error) {var cc * clientConn createConn: = false startCleaner: = false var n int c.connsLock.Lock () n = len (c.conns) if n = 0 {maxConns: = c.MaxConns if maxConns
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.