記一次Golang routine卡死

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Go語言最方便的地方在於可以自由自在的起routine,並且不用自己維護隊列。

 

一個很簡單的處理模型,針對於長串連活動平凡的連結獨立routine進行處理,方便同一串連上下文關聯,read routine A講接收到的訊息解包產生訊息丟到對應socket的routine B channel中進行處理,routine B在根據不同的任務丟到對應的routine B1或者 routine B2中進行處理,

我們需要一個channel回寫routine B1 routine B2的退出訊號給你 B 以便B進行響應處理。

那麼這麼想的話 B 和B1 B2 需要兩個channel進行訊息通訊

虛擬碼如下,未做友好處理。

var B1 B1Consumervar B2 B2Consumer//statch 回寫子routine的狀態statch := make(chan StatMsg,1)B1Ch := make(chan Msg,100)B2Ch := make(chan Msg,100)go B1(B1ch,statch)go B2(B2ch,statch)for{    select{    case cmsg, ok := <-BCh:        if cmsg.type == B1{            B1ch<-cmsg        }else{            B2ch<-cmsg        }    case StatMsg := <-statch:        deal_state(msg)    }}

乍一看沒什麼問題,後面再測試過程中 偶爾發現調用介面沒有響應逾時。

仔細排查後發現,B1 routine 在退出時回寫了一個Done的StatMsg,然後就退出了。

此事Bch還在寫資料如果此時B1ch寫滿了,那麼寫channel就會卡死,而B1退出的訊號已經發送了 不在處理新資料了,那麼B routine就會一直卡死在

B1ch<-cmsg

此時已經B routine 已經無法進行下一次select的操作,進而等Bch channel寫滿 卡死讀取routine,等多個讀取routine卡死,用戶端表現就是無響應了 逾時了。

 

找到問題解決辦法就簡單了。

增加寫入channel逾時 並且增加statch 的大小

statch := make(chan StatMsg,MAXCHANNELSIZE) select {            case B1ch <- cmsg:            case <-time.After(time.Duration(CLOSETIMEOUT) * time.Second):}

 

加大channel大小 避免多次觸發逾時,如果一旦出現逾時,將逾時的任務釋放掉。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.