寫書寫到一半,強迫症發作跑去給HotChocolate修bug

前言

這是寫作《C#與.NET6 開發從入門到實踐》時的小故事,作爲本書正式上市的宣傳,在此分享給大家。

正文

.NET目前有兩個比較成熟的GraphQL框架,其中一個是HotChocolate,在使用對比後認爲這個使用更方便,因此將其作爲本書的介紹內容。結果在研究客戶端訂閱的時候發現一個bug:如果訂閱因爲異常(例如網絡掉線)而結束,訂閱不會有任何反應(只是這個訂閱永遠不會再收到數據)。我就在想,如果一個訂閱長時間沒有收到數據,到底是因爲出問題了還是隻是單純的沒有新數據。

隨後我就跑到GitHub上提交問題,結果作者並沒有理解我的意思,然後就不了了之。最後在準備實戰演練的項目時又用到了客戶端,又想起來這個bug,就當場強迫症發作又給作者提問題,結果又是石沉大海。無奈乾脆下載代碼親自研究客戶端到底是哪裏出問題導致這個bug。感興趣的朋友可以看看https://github.com/ChilliCream/graphql-platform/issues/5006

這裏我就簡單介紹一下問題的原因和處理方法。客戶端在WebSocket和訂閱實例之間使用Pipeline作爲中介,然後使用Channel向用戶API傳遞解析後的對象。其中數據讀取和寫入使用兩個Task分別負責,讀取WebSocket寫入Pipeline的Task在循環讀取WebSocket的時候沒有向Channel傳遞表示連接結束的對象,導致客戶端實例不知道實情,最後用戶API沒有任何反。用戶API中使用的IObserver也是一個關鍵點,客戶端在訂閱異常結束時沒有調用Complete方法通知觀察者數據流已經結束,導致用戶API沒有反應。根據微軟文檔,應該在確定數據流結束後調用Complete方法通知觀察者結束觀察,無論數據流因何結束。

客戶端使用的Pipeline是一個網絡數據緩存的優秀中介,手動處理粘包數據是非常麻煩的,Pipeline就專門負責管理數據是否被消耗,查看過但沒有被消耗的數據應該如何處理。新的Span和Memory類型則可以實現直接訪問緩衝區內存,避免查看但不消耗數據的情況下反覆複製內存導致性能下降和內存佔用上升。

結果作者在使用Pipeline之後切斷了WebSocket和用戶API之間的直接聯繫又沒有處理相關情況最後導致了這個bug。目前作者正在考慮改用其他方式實現客戶端,這個問題也許會自然消失。我的修復已經合併到主分支,不過被標記到13.0上,但是客戶端目前12.0和13.0的包共存,12.0的代碼生成器生成的代碼和13.0的實現不兼容。不知道12.0版有沒有包含修復。

結語

這個問題前前後後歷時將近半年,真是把我折磨的夠嗆。最後請讓我再宣傳一次我的新書《C#與.NET6 開發從入門到實踐》。詳情請看《C#與.NET6 開發從入門到實踐》上市,作者親自來打廣告了!

QQ羣

讀者交流QQ羣:540719365
image

歡迎讀者和廣大朋友一起交流,如發現本書錯誤也歡迎通過博客園、QQ羣等方式告知我。

購買方式:
京東自營:https://item.jd.com/13860498.html
噹噹自營:https://product.dangdang.com/29546824.html

本文地址:https://www.cnblogs.com/coredx/p/17253035.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章