当前位置:网站首页>A troubleshooting of golang memory leak
A troubleshooting of golang memory leak
2022-06-24 16:17:00 【Johns】
background
Recently in use golang Develop a content recommendation project , It was found that the vessel would restart after a period of time before the pressure test was planned , When checking the memory of the machine, it is found that the memory has been rising since startup , Then restart after reaching the maximum available memory threshold of a container . Here's the picture :
From the above chart, it can be concluded that , Memory leaks .
The screening process
One thing to note is that golang Is based on goroutine On schedule , therefore goland Ninety percent of memory leaks come from goroutine Memory leak , We just need to keep an eye on goroutine The most places , You can basically find the source of the memory leak .
I use the go Of pprof The tool has been debugged and checked , First, introduce this component into the project , And desensitize all the codes that may leak business information .
package main import ( "fmt" "net/http" _ "net/http/pprof" ) func main() { // Ignore other codes //pprof server http.ListenAndServe("localhost:8080", nil) // Ignore other codes }
First, let's take a look at the situation when there is no traffic at startup ,CPU And memory allocation :
Let's go in goroutine You can see a total of 21 individual goroutine, The most 5 One is used to run timed tasks . At present, the project is normal .
Because my service has multiple external interfaces , So I turn off the other interface routes first , Then use the pressure measuring tool for pressure measurement ( What I'm using here is go-stress-testing)
Then let's look at pprof The indicators of
Find out goroutine It's skyrocketing , Click in and find that there is 1001 individual redis pool object , It's normal for us redis The connection pool will only have 1 One of the .
My code is like this
package utils import ( "fmt" "github.com/go-redis/redis/v8" "time" ) func GetRedisClient() *redis.Client { redisCli := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB PoolSize: 20, MinIdleConns: 10, IdleTimeout: 3 * time.Minute, }) if redisCli != nil { return redisCli } else { fmt.Sprint("redis client is nil") return nil } }
Use redisClient
The local code for is
func (s baseService) Multiply(ctx context.Context, in *pb.MultiplyRequest) (errCode int32, resp *pb.MultiplyResponse, err error) { // Ignore other codes redisCli := utils.GetRedisClient() userFeat, err := redisCli.Get(ctx, "user_feat:" + uid).Result() if err != nil { return comn.SUCC.Code, &pb.MultiplyResponse{ Code: comn.ErrRequestParamIllegal.Code, Msg: comn.ErrRequestParamIllegal.Msg, }, nil } // Ignore other codes }
Found it. , original go-redis Under bag redis.Client It's a Connect pool objects Not a simple one Client connection
Knowing the problem, we just need to redis.Client Initialize as a global object , Each time you need to use it, you can directly reuse the previous connection pool .
The code is adjusted as follows :
import ( "fmt" "github.com/go-redis/redis/v8" "time" ) var RedisClient *redis.Client func init() { RedisClient = redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password set DB: 0, // use default DB PoolSize: 20, MinIdleConns: 10, IdleTimeout: 3 * time.Minute, }) fmt.Sprint(RedisClient) }
Reuse directly each time a request comes redis.Client Just go :
func (s baseService) Multiply(ctx context.Context, in *pb.MultiplyRequest) (errCode int32, resp *pb.MultiplyResponse, err error) { // Ignore other codes userFeat, err := utils.RedisClient.Get(ctx, "user_feat:" + uid).Result() if err != nil { return comn.SUCC.Code, &pb.MultiplyResponse{ Code: comn.ErrRequestParamIllegal.Code, Msg: comn.ErrRequestParamIllegal.Msg, }, nil } // Ignore other codes }
Restart , Pressure test again :
The discovery is basically goroutine The quantity of is kept at a reasonable value .
Then release the code to the test container , After a period of time, the memory usage in the monitor is basically normal .
summary
- golang Most memory leaks are caused by goroutine Caused by leakage , So we should first focus on the overall goroutine Number .
- image redis,mysql This relatively scarce resource can be used Connection pool But pay attention to the size of the control pool , And the timeout for each connection , Pay attention to timely release after use . and go Yes redis also mysql Both have built-in connection pools , You must find out what the initialized instance is .
边栏推荐
- #夏日挑战赛# HarmonyOS - 实现带日期效果的待办事项
- Istio FAQ: sidecar stop sequence
- Golang+redis distributed mutex
- 打破内存墙的新利器成行业“热搜”!持久内存让打工人也能玩转海量数据+高维模型
- Logging is not as simple as you think
- Batch BOM Bapi test
- Advanced programmers must know and master. This article explains in detail the principle of MySQL master-slave synchronization
- [log service CLS] Tencent cloud log4j/logback log collection best practices
- April 26, 2021: the length of the integer array arr is n (3 < = n < = 10^4), and each number is
- 【Prometheus】2. Overview and deployment
猜你喜欢
How to easily realize online karaoke room and sing "mountain sea" with Wang Xinling
Nifi from introduction to practice (nanny level tutorial) - environment
使用阿里云RDS for SQL Server性能洞察优化数据库负载-初识性能洞察
One article explains Jackson configuration information in detail
【云原生 | Kubernetes篇】Kubernetes基础入门(三)
[download attached] installation and simple use of Chinese version of awvs
ZOJ——4104 Sequence in the Pocket(思维问题)
B. Terry sequence (thinking + greed) codeforces round 665 (Div. 2)
Using oasis to develop a hop by hop (I) -- Scene Building
Cap: multiple attention mechanism, interesting fine-grained classification scheme | AAAI 2021
随机推荐
Rush for IPO, Hello, I'm in a hurry
Is Shanjin futures safe? What are the procedures for opening futures accounts? How to reduce the futures commission?
MySQL InnoDB and MyISAM
ThinkPHP vulnerability exploitation tool
Fastjson 漏洞利用技巧
[cloud native | kubernetes chapter] Introduction to kubernetes Foundation (III)
企业安全攻击面分析工具
Siggraph 2022 | truly restore the hand muscles. This time, the digital human hands have bones, muscles and skin
2021-04-29: given an array arr, it represents a row of balloons with scores. One for each blow
Some adventurer hybrid versions with potential safety hazards will be recalled
Global and Chinese markets of Leyte coin exchange 2022-2028: Research Report on technology, participants, trends, market size and share
Leetcode notes of Google boss | necessary for school recruitment!
ZOJ——4104 Sequence in the Pocket(思维问题)
一文详解JackSon配置信息
Nature publishes significant progress in quantum computing: the first quantum integrated circuit implementation in history
Istio FAQ: virtualservice route matching sequence
一文详解JackSon配置信息
几种常见的DoS攻击
Interpretation of swin transformer source code
Golang+redis distributed mutex