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

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級(jí)程式碼編輯軟體(SublimeText3)

Golang主要用於後端開發(fā),但也能在前端領(lǐng)域間接發(fā)揮作用。其設(shè)計(jì)目標(biāo)聚焦高性能、並發(fā)處理和系統(tǒng)級(jí)編程,適合構(gòu)建API服務(wù)器、微服務(wù)、分佈式系統(tǒng)、數(shù)據(jù)庫操作及CLI工具等後端應(yīng)用。雖然Golang不是網(wǎng)頁前端的主流語言,但可通過GopherJS編譯成JavaScript、通過TinyGo運(yùn)行於WebAssembly,或搭配模板引擎生成HTML頁面來參與前端開發(fā)。然而,現(xiàn)代前端開發(fā)仍需依賴JavaScript/TypeScript及其生態(tài)。因此,Golang更適合以高性能後端為核心的技術(shù)棧選擇。

要構(gòu)建一個(gè)GraphQLAPI在Go語言中,推薦使用gqlgen庫以提高開發(fā)效率。 1.首先選擇合適的庫,如gqlgen,它支持根據(jù)schema自動(dòng)生成代碼;2.接著定義GraphQLschema,描述API的結(jié)構(gòu)和查詢?nèi)肟?,如定義Post類型和查詢方法;3.然後初始化項(xiàng)目並生成基礎(chǔ)代碼,實(shí)現(xiàn)resolver中的業(yè)務(wù)邏輯;4.最後將GraphQLhandler接入HTTPserver,通過內(nèi)置Playground測試API。注意事項(xiàng)包括字段命名規(guī)範(fàn)、錯(cuò)誤處理、性能優(yōu)化及安全設(shè)置等,確保項(xiàng)目可維護(hù)性

安裝Go的關(guān)鍵在於選擇正確版本、配置環(huán)境變量並驗(yàn)證安裝。 1.前往官網(wǎng)下載對(duì)應(yīng)系統(tǒng)的安裝包,Windows使用.msi文件,macOS使用.pkg文件,Linux使用.tar.gz文件並解壓至/usr/local目錄;2.配置環(huán)境變量,在Linux/macOS中編輯~/.bashrc或~/.zshrc添加PATH和GOPATH,Windows則在系統(tǒng)屬性中設(shè)置PATH為Go的安裝路徑;3.使用goversion命令驗(yàn)證安裝,並運(yùn)行測試程序hello.go確認(rèn)編譯執(zhí)行正常。整個(gè)流程中PATH設(shè)置和環(huán)

sync.WaitGroup用於等待一組goroutine完成任務(wù),其核心是通過Add、Done、Wait三個(gè)方法協(xié)同工作。 1.Add(n)設(shè)置需等待的goroutine數(shù)量;2.Done()在每個(gè)goroutine結(jié)束時(shí)調(diào)用,計(jì)數(shù)減一;3.Wait()阻塞主協(xié)程直到所有任務(wù)完成。使用時(shí)需注意:Add應(yīng)在goroutine外調(diào)用、避免重複Wait、務(wù)必確保Done被調(diào)用,推薦配合defer使用。常見於並發(fā)抓取網(wǎng)頁、批量數(shù)據(jù)處理等場景,能有效控制並發(fā)流程。

音視頻處理的核心在於理解基本流程與優(yōu)化方法。 1.其基本流程包括採集、編碼、傳輸、解碼和播放,每個(gè)環(huán)節(jié)均有技術(shù)難點(diǎn);2.常見問題如音畫不同步、卡頓延遲、聲音噪音、畫面模糊等,可通過同步調(diào)整、編碼優(yōu)化、降噪模塊、參數(shù)調(diào)節(jié)等方式解決;3.推薦使用FFmpeg、OpenCV、WebRTC、GStreamer等工具實(shí)現(xiàn)功能;4.性能管理方面應(yīng)注重硬件加速、合理設(shè)置分辨率幀率、控制並發(fā)及內(nèi)存洩漏問題。掌握這些關(guān)鍵點(diǎn)有助於提升開發(fā)效率和用戶體驗(yàn)。

使用Go的embed包可以方便地將靜態(tài)資源嵌入二進(jìn)制,適合Web服務(wù)打包HTML、CSS、圖片等文件。 1.聲明嵌入資源需在變量前加//go:embed註釋,如嵌入單個(gè)文件hello.txt;2.可嵌入整個(gè)目錄如static/*,通過embed.FS實(shí)現(xiàn)多文件打包;3.開發(fā)時(shí)建議通過buildtag或環(huán)境變量切換磁盤加載模式以提高效率;4.注意路徑正確性、文件大小限制及嵌入資源的只讀特性。合理使用embed能簡化部署並優(yōu)化項(xiàng)目結(jié)構(gòu)。

搭建一個(gè)用Go編寫的Web服務(wù)器並不難,核心在於利用net/http包實(shí)現(xiàn)基礎(chǔ)服務(wù)。 1.使用net/http啟動(dòng)最簡服務(wù)器:通過幾行代碼註冊(cè)處理函數(shù)並監(jiān)聽端口;2.路由管理:使用ServeMux組織多個(gè)接口路徑,便於結(jié)構(gòu)化管理;3.常見做法:按功能模塊分組路由,並可用第三方庫支持複雜匹配;4.靜態(tài)文件服務(wù):通過http.FileServer提供HTML、CSS和JS文件;5.性能與安全:啟用HTTPS、限制請(qǐng)求體大小、設(shè)置超時(shí)時(shí)間以提升安全性與性能。掌握這些要點(diǎn)後,擴(kuò)展功能將更加容易。

select加default的作用是讓select在沒有其他分支就緒時(shí)執(zhí)行默認(rèn)行為,避免程序阻塞。 1.非阻塞地從channel接收數(shù)據(jù)時(shí),若channel為空,會(huì)直接進(jìn)入default分支;2.結(jié)合time.After或ticker定時(shí)嘗試發(fā)送數(shù)據(jù),若channel滿則不阻塞而跳過;3.防止死鎖,在不確定channel是否被關(guān)閉時(shí)避免程序卡?。皇褂脮r(shí)需注意default分支會(huì)立即執(zhí)行,不能濫用,且default與case互斥,不會(huì)同時(shí)執(zhí)行。
