在我們開始之前,先介紹一下我是誰以及為什麼它在這種情況下很重要。我是筆記本製造公司的軟體開發人員,過去兩年在這裡工作。在我現在所在的團隊中,我是唯一的開發人員,負責使用 Go 和 Grafana 創建、監控和維護資料管道、自動化以及監控系統。
我還要補充一點,前一年我是實習生。而且我是自學的。
嗯,當我遇到自己無法解決的障礙或問題時,我沒有高級開發人員,也沒有任何形式的內部指導可以指導我,這就是我寫作的主要原因。我認為這是一件有趣的事情並且想要分享。它不會是一個令人驚嘆的軟體,一個突破或類似的東西,但它提醒我們從頭開始建立東西是可能的。您不需要成為百萬分之一的 10 倍開發人員或類似的人。
P.S:順便說一句,我使用 neovim。
這個數字可能看起來有些誇張或類似的東西,儘管我希望如此,但事實並非如此。看,在製造環境中工作時,有時我們不會考慮需要多少個項目,以及當您必須追蹤每個組件的許多製造隊列的每個點時它會產生多少數據。
無論是一個小螺絲,還是上一代 CPU,都必須被跟踪,帶有時間戳!
所以,是的,產生的資料量是正確的,而這只是開始。以下是讓問題變得很酷的其他酷點(在我看來):
這就是整個上下文,現在有趣的部分開始。
我喜歡使用軟體的方式非常簡單。讓它變得醜陋且幾乎不起作用->保持醜陋並改進功能->仍然醜陋,但優化得更好->漂亮、優化且工作->然後你的經理說你所做的工作太好了,源無法處理它,導致中斷。臥槽。
無論如何,DMP 代表 Dumb Mode Protocol,只要讓它以最愚蠢的方式工作即可,這意味著勉強可以工作。
所以,對於第一輪,我的目標很簡單,進行身份驗證,發出請求,解析數據,發送到資料庫。很簡單,對吧?而且,在紙面上,它是,直到我發現我必須使用的身份驗證和授權方法是 ntlmssp,這是我不知道存在的質詢回應身份驗證方法。事實上,我必須進入舊版 .NET 4 程式碼才能找到它。我沒學過C#。
在瀏覽了比我年長的遺留程式碼之後,我在嘗試理解它時遇到了困難,因為出於某種原因,編寫它的人認為將其隱藏到5 層抽象、構造函數和OOP 中是一個好主意。不有趣,令人羞愧的經驗。然後我成功了。一小時後,我的用戶被封鎖,因為顯然該來源有速率限制。但沒有快取或延遲載入。
好吧,在這一切之後,我只需要傳遞查詢參數並獲取數據,不再需要來源的複雜性。好吧,我們來查一下查詢參數的文檔。
...
此時,考慮到所有因素,您可能猜對了。文件?這是只有矽谷才有的異國美食嗎?
不管怎樣,在絞盡腦汁之後,我決定檢查一下這個 SQL Server Reporting Services 的網站/介面,令我高興的是,然後是仇恨,它有一種方法來了解過濾器及其值。
只知道頁面中的(「全部」)過濾器,例如選擇所有生產線,只是選取所有框的抽象。好吧,讓我們複製過濾器並將其放入查詢字串中,對其進行編碼,然後開心!
還記得我說過我的用戶被封鎖了嗎?好吧,看起來擁有執行此類任務的管理員權限,並由 C-Suite 授權執行此操作(事實上,這是他們要求的),但不足以允許我執行多個請求。我的用戶被封鎖了,但是,對於我的經理來說,這就像說「什麼也沒發生」。幸運的是,我很快就解封了。
與此同時,我決定按照我處理該專案其餘部分的方式進行工作。此時我已經有了一個樣本,它符合帖子的標題。看到這七位數讓我懷疑自己是否能做到,因為我對這個數據量的經驗是零。
為了將我的想法付諸實踐,我希望進入 exlidraw 並設計出我想做的事情。我知道工作池的概念,但之前沒有實現過。因此,我閱讀了相關內容,看到了一些實現,並詢問了一位對我幫助很大的朋友。他是我沒有的前輩。
用偽代碼寫出來後,我心裡想:
「哇,這非常簡潔,所有這些通道和 goroutine 肯定不會產生記憶體洩漏,對吧?」
好吧,可能不是那些確切的詞,但大致意思是這樣的。在完成第一次迭代、設法執行請求(不會被阻止)並將其加載到記憶體之後,我應用了工作池概念。
然後我遇到了 BSOD。有趣的是,就在 CrowdStrike 罷工的同一天,我當然不認為我造成了工廠的重大停電。
另外,是的,我必須使用 Windows 來工作,但不用擔心!我使用 WSL2。
在檢查了我的第一次堆疊溢出的大量堆疊追蹤後,我發現了這個錯誤。在將資料傳送到消費者通道時,我沒有考慮到某些資料可能會出錯,主要是由於違反了主鍵,或者只是因為,也許,我沒有正確處理錯誤。
經驗教訓,使用錯誤通道來避免重大問題。並處理您的錯誤,無論是通過簡單的字符串檢查(醜陋,但有效),或者只是頂級記錄它,然後高興。由於我遇到的錯誤並不嚴重,所以我可以繼續。
這一步產生的記憶體洩漏量讓我以為我在做 C。但這只是主要的技能問題。
不管怎樣,你可能會想:
「你是如何在如此簡單的過程中造成記憶體洩漏的?」
很簡單,我正在學習和嘗試。
這一步中的主要問題是我天真地沒有確保資料被正確插入,並且我得到的主鍵違規量違反了我的記憶。這是我知道如何解決的問題,讓我們快取資料吧!
等等,考慮到每一行都是唯一的,如何為每一行建立一個唯一識別碼?
現在,這是很多人會嘲笑我的部分,因為,公平地說,這是最讓我崩潰的部分。我只是簡單地添加當前行的信息並將其解析為哈希函數,該哈希就成為我在映射中的鍵。
「為什麼不使用 Redis?」 - 你可能會問自己。
很簡單,官僚主義。這不是一家小公司。事實上,你們中的許多人可能正在使用他們製造的筆記型電腦。請求一個 Redis 實例這個簡單的行為至少需要三個工作日、四次會議、對官僚之神的犧牲,以及一份解釋原因和方式的完整文件。
所以,是的,讓我們使用簡單的哈希圖並在第一次運行之前對其進行預初始化。它會增加整體載入時間,但會比請求更快。
透過這樣做,整個過程得到了改善,就像有了一個新馬達一樣,memleaks 停止了,批次不會每次都失敗,錯誤和斷開連接的數量也減少了,非常好,對吧?對嗎?
現在,您知道有些事情變得混亂了。
我沒有考慮到的一點是,透過批次插入,可以驗證資料。這是流程的簡單表示。
取得資料->檢查hashmap中是否存在資料的hash ->批次&插入
這有什麼問題嗎?那麼,如果我的批次中的單一插入失敗,會發生什麼情況,它會在沒有條目的情況下重試嗎?如果是這樣,我可以重試多少次而不會使系統混亂並失去工作池實現的優勢?
只有一個方法可以找出答案!我們來檢查一下。
我要補充的一點是,該來源傳回了超過 25 列,因此我必須小心每批插入的資料量,以免超過 2100 個參數,這是 MSSQL 的限制。
此時,我已經在 Docker 容器中運行一些東西,該容器模仿資源有限的生產空間。為了添加上下文,該進程使用 1GB RAM 和大約 0.5CPU 運行。我本來可以分配更多的資源,但這只是強行逼我出路。
透過在容器內運行這個新的迭代,添加一些時間戳並將其記錄到文件中以供以後分析。我發現由於重試次數增加了大約 5 分鐘。這是行不通的,刪除「髒」條目不是選項。
為了解決這個問題,我增加了工人的數量。我使用了大約 50 名工作人員,並且由於 ThePrimagen 頂級貨架上的不和諧用戶的隨機猜測,我將其增加到 1000 名工作人員,並確保每個工作人員都驗證交易中的每個條目。萬一交易失敗,我直接回滾。
透過這樣做,我能夠解決核心問題並整體提高該過程的整體速度。現在是時候將其放入產品中並對其進行監控了,因為,你知道,產品妖精可能會弄亂你的軟體。 (它們也被稱為技能問題,但這個名稱是禁止的。)
知道減少該系統的獲取間隔,要求使其接近實時(這意味著足夠快,讓他們不會注意到延遲),我創建了一個新容器,這一次具有更強健的功能檢查是否能夠承受負載,並將間隔設定為3 分鐘。考慮到平均獲取時間,這意味著我可能會有一些重疊,但我真的很想看看會發生什麼。
我讓它運行了一夜,記錄結果以便稍後查看,令我驚訝的是,在工作日結束之前,我接到了經理的電話。請注意,他不是技術人員或類似的人。
「嘿,『我們』部署了一些與[我無法透露的系統名稱]互動的東西嗎?」
「是的,我按照要求即時部署了資料擷取系統。為什麼?」
「你能,嗯,停下來嗎?它導致了停電,我們無法在這裡工作。」_
這,gadies and lentleman,完全是另一個層次的破壞性刺激。毫不誇張地說,我讓 20 多條生產線停止了一分鐘左右。無論如何,我停止了系統,一切都恢復正常。
第二天,我被要求將讀取之間的間隔從 3 分鐘增加到 30 分鐘,好吧,我想沒問題。我不會說謊,我有點難過,因為我無法看到它以最大速度運行,但是嘿,至少我讓它工作了。
使用這個新系統,使用該數據的報告的平均更新時間減少到 8~10 秒,這導致經理以相同的方式請求更多相同來源的報告。好的工作會得到更多工作的回報!
這是一次有趣的經歷,主要是因為它讓我真正意識到 Go 的強大之處。使用比谷歌瀏覽器更少的內存,比微軟應用程式更少的存儲空間,比Windows 計算器更少的CPU 功率,我能夠改進一個舊的進程,這個進程實際上是暴力強制通過的(它在插入之前實際上檢查了資料庫中的每一行。 )。真的很有趣。
無論如何,請隨意分享您在整個過程中的想法,您會如何處理以及您會採取哪些不同的做法。由於我沒有開發同事,我想了解更多我對此的看法。
以上是我如何處理每個請求的條目 - 使用 Go!的詳細內容。更多資訊請關注PHP中文網其他相關文章!