<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Go的奇妙之處在於,我們可以使用goroutines和channel輕鬆地執行並行任務。如果在生產環境中使用goroutines和channel,但是不瞭解它們的行為方式,會造成一些嚴重的影響。
好吧,我們就面臨著這樣的影響,我們在goroutines中出現了洩漏,導致應用伺服器隨著時間的推移而膨脹,消耗了大量的CPU和頻繁的GC,影響了多個服務的SLA。
從本文中可以看到什麼
理解什麼是goroutine洩露。 理解goroutine洩漏的多種方式。 詳細瞭解造成goroutine洩露的一個真實場景。 我們是如何找到goroutine洩漏原因? 阻止goroutine洩漏的最佳實踐是什麼?
正如你在上面所附的指標中所看到的,goroutines開始隨著時間的推移成倍地飆升。唯一的一次下降是當我們的一個正在執行的範例被AWS排程走,新的範例被啟動,或者有一個新的版本,殺死了現有的容器併產生了新的容器。
如果你觀察GC暫停的時間,它會隨著活動的goroutine的數量不斷增加。GC暫停的次數越多,CPU利用率就越高,響應時間也越來越長。
goroutine洩漏是指使用者端生成一個goroutine來做一些非同步任務,並在任務完成後將一些資料寫入一個channel,但是
沒有監聽程式消耗該channel的資料寫入。
在上述情況下,程式碼成功地完成了執行,好像根本就沒有問題。但這裡發生的情況是,會有一個沒有被管理的goroutine駐留在記憶體中,佔用CPU和RAM。
主要原因是第3行,我們正在向一個通道寫入資料,但根據Go原則,一個未緩衝的通道會阻止向通道的寫入,直到消費者從該channel取走資訊。
所以在這種情況下,第4行的返回將永遠不會被執行,並且newgoroutine函數在整個應用程式生命週期中都被卡住,因為這個channel沒有消費者。
在goroutine啟動和channel監聽器之間有一些條件邏輯。
在這個案例中,有一個小小的改進。我們有一個消費者從dataChan中消費資料,但是從我們生成goroutine開始,到我們開始從通道中消費資料之前,有大量的應用程式程式碼駐留在那裡,這些程式碼可以在一些處理錯誤|DB錯誤|無指標異常|panic的情況下退出主函數,由於這些原因,channel的資料可能從未被執行。
這就是一個goroutine看似正常,實際可能導致洩漏的情況。
我們不能在應用處理之前將channel中的值提前消費,因為消費者會阻止剩下業務邏輯的處理,直到它收到資料,從而消除了並行任務的執行。
傳送完成立刻返回 以上兩種情況是當goroutine因為沒有channle的消費者而被阻塞,或者消費者從channel中消費資料的程式碼塊被跳過。
當我們把一個channel傳遞給goroutine去消費時,當傳送者向通道傳送資料時出現了問題,這是否也是同樣的情況?
好吧,95%的goroutine洩露都是因為這3種情況中的一種,在我們的案例中,是由於情景-2。我們在GoIbibo-Makemytrip的工作是折扣和便利費服務。
當客戶應用一個促銷程式碼時,我們有一套規則要執行,以找出正確的折扣。我們有另一個微服務,我們稱之為實時動態折扣器(DD),它試圖根據一些演演算法(黑盒子)來計算折扣。
這個動態折扣是一個A/B實驗,只有10%的使用者會參與其中。只有當我們的靜態規則中存在有效的折扣時,我們才會覆蓋DD折扣。
我們只有在處理完靜態規則後才需要DD的響應。所以來自ddChan的消費將在最後進行。
如果靜態規則的評估有問題|如果沒有滿足請求的有效規則|如果使用者應用了一些假的促銷活動,我們從ddChan中消耗資料的程式碼將無法到達,這導致loadDDDiscount函數成為一個無法控制的goroutine。
方法-1 方法 -> 從我們啟動goroutine開始,到我們從退出channel的消耗資料為止,我們識別每一個錯誤條件,並在每一個返回語句前放置一個接收者,以解除對生成的goroutine的封鎖。
陷阱 -> 我們必須手動找到所有的邊緣情況,並且在將來,如果我們必須處理更多的錯誤情況,我們需要記住在返回之前我們需要消耗哪些channel的資料。
方法-2 方法 -> 與其在每個錯誤的情況下放置一個接收者,為什麼不設定一個可以從channel中接收資料的延遲函數。
陷阱 -- 在成功的情況下,資料將在處理完靜態規則後從通道中讀取。因此,如果我們在defer函數中開始接收通道中的資料,那麼在成功的情況下就會阻塞主goroutine。
方法-3 沒有完美的方法。在上述所有場景中,我們建立了一個無緩衝的通道,阻止傳送者向該通道傳送資料,直到接收者收到資料。這裡的主要問題是我們不確定由於我們的應用處理,接收方是否會被執行。那麼,簡單的解決方案是建立一個上限為1的緩衝通道。有了這個,即使沒有消費者,或者消費者程式碼沒有達到,傳送者也不會被阻止寫一次資料。 圖片 陷阱 -> 絕對是零。這與非緩衝通道的工作原理完全相同,但為我們提供了一個額外的能力,即傳送者在傳送資料時不會受到阻礙,而消費者可以在任何時候消費它,而且生成的goroutine也不會等待消費者的到來。 我們用第三種方法將變化帶入生產環境,你可以看到顯著的影響。
圖片 以前是線性增長的goroutine數量,現在下降到150個,我們的GC暫停頻率也是如此。
整個事情中最痛苦的部分是,如何找到程式碼中存在goroutine洩漏的部分?
所以我的方法是這樣的。
當伺服器啟動時,使用debug.SetGCPercent(-1)禁用垃圾收集器。 現在執行程式碼中每一個使用Go程式的流程(Dev Env)。 在每個API的入口處,列印在開始和執行API之前和之後執行的goroutines的數量。
func ApplyPromo() { fmt.Println(runtime.NumGoroutine()) defer fmt.Println(runtime.NumGoroutine() // Process your application logic }
現在,如果一個服務在前後返回不同的Goroutines數量,那麼這個邏輯就存在洩漏。
我們有近20個API和大約35-40個地方使用了goroutines以改善並行性。幸運的是,我能夠在前3次迭代中找出洩漏問題,並行現了這個存在洩漏的邏輯。
以上就是goroutine 洩漏和避免洩漏實戰範例的詳細內容,更多關於goroutine 洩漏避免洩漏的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45