欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

go語(yǔ)言fork進(jìn)程 go go for

GO語(yǔ)言(二十七):管理依賴項(xiàng)(下)-

當(dāng)您對(duì)外部模塊的存儲(chǔ)庫(kù)進(jìn)行了 fork (例如修復(fù)模塊代碼中的問(wèn)題或添加功能)時(shí),您可以讓 Go 工具將您的 fork 用于模塊的源代碼。這對(duì)于測(cè)試您自己的代碼的更改很有用。

創(chuàng)新互聯(lián)建站專注于蒲城網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供蒲城營(yíng)銷型網(wǎng)站建設(shè),蒲城網(wǎng)站制作、蒲城網(wǎng)頁(yè)設(shè)計(jì)、蒲城網(wǎng)站官網(wǎng)定制、成都小程序開(kāi)發(fā)服務(wù),打造蒲城網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供蒲城網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。

為此,您可以使用go.mod 文件中的replace指令將外部模塊的原始模塊路徑替換為存儲(chǔ)庫(kù)中 fork 的路徑。這指示 Go 工具在編譯時(shí)使用替換路徑(fork 的位置),例如,同時(shí)允許您保留import 原始模塊路徑中的語(yǔ)句不變。

在以下 go.mod 文件示例中,當(dāng)前模塊需要外部模塊example.com/theirmodule。然后該replace指令將原始模塊路徑替換為example.com/myfork/theirmodule模塊自己的存儲(chǔ)庫(kù)的分支。

設(shè)置require/replace對(duì)時(shí),使用 Go 工具命令確保文件描述的需求保持一致。使用go list命令獲取當(dāng)前模塊正在使用的版本。然后使用go mod edit命令將需要的模塊替換為fork:

注意: 當(dāng)您使用該replace指令時(shí),Go 工具不會(huì)像添加依賴項(xiàng)中所述對(duì)外部模塊進(jìn)行身份驗(yàn)證。

您可以使用go get命令從其存儲(chǔ)庫(kù)中的特定提交為模塊添加未發(fā)布的代碼。

為此,您使用go get命令,用符號(hào)@指定您想要的代碼 。當(dāng)您使用go get時(shí),該命令將向您的 go.mod 文件添加一個(gè) 需要外部模塊的require指令,使用基于有關(guān)提交的詳細(xì)信息的偽版本號(hào)。

以下示例提供了一些說(shuō)明。這些基于源位于 git 存儲(chǔ)庫(kù)中的模塊。

當(dāng)您的代碼不再使用模塊中的任何包時(shí),您可以停止將該模塊作為依賴項(xiàng)進(jìn)行跟蹤。

要停止跟蹤所有未使用的模塊,請(qǐng)運(yùn)行g(shù)o mod tidy 命令。此命令還可能添加在模塊中構(gòu)建包所需的缺失依賴項(xiàng)。

要?jiǎng)h除特定依賴項(xiàng),請(qǐng)使用go get,指定模塊的模塊路徑并附加 @none,如下例所示:

go get命令還將降級(jí)或刪除依賴于已刪除模塊的其他依賴項(xiàng)。

當(dāng)您使用 Go 工具處理模塊時(shí),這些工具默認(rèn)從 proxy.golang.org(一個(gè)公共的 Google 運(yùn)行的模塊鏡像)或直接從模塊的存儲(chǔ)庫(kù)下載模塊。您可以指定 Go 工具應(yīng)該使用另一個(gè)代理服務(wù)器來(lái)下載和驗(yàn)證模塊。

如果您(或您的團(tuán)隊(duì))已經(jīng)設(shè)置或選擇了您想要使用的不同模塊代理服務(wù)器,您可能想要這樣做。例如,有些人設(shè)置了模塊代理服務(wù)器,以便更好地控制依賴項(xiàng)的使用方式。

要為 Go 工具指定另一個(gè)模塊代理服務(wù)器,請(qǐng)將GOPROXY 環(huán)境變量設(shè)置為一個(gè)或多個(gè)服務(wù)器的 URL。Go 工具將按照您指定的順序嘗試每個(gè) URL。默認(rèn)情況下,GOPROXY首先指定一個(gè)公共的 Google 運(yùn)行模塊代理,然后從模塊的存儲(chǔ)庫(kù)直接下載(在其模塊路徑中指定):

您可以將變量設(shè)置為其他模塊代理服務(wù)器的 URL,用逗號(hào)或管道分隔 URL。

Go 模塊經(jīng)常在公共互聯(lián)網(wǎng)上不可用的版本控制服務(wù)器和模塊代理上開(kāi)發(fā)和分發(fā)。您可以設(shè)置 GOPRIVATE環(huán)境變量。您可以設(shè)置GOPRIVATE環(huán)境變量來(lái)配置go命令以從私有源下載和構(gòu)建模塊。然后 go 命令可以從私有源下載和構(gòu)建模塊。

GOPRIVATE或環(huán)境變量可以設(shè)置為匹配模塊前綴的全局模式列表,這些GONOPROXY前綴是私有的,不應(yīng)從任何代理請(qǐng)求。例如:

為什么要使用 Go 語(yǔ)言,Go 語(yǔ)言的優(yōu)勢(shì)在哪里

部署簡(jiǎn)單。Go編譯生成的是一個(gè)靜態(tài)可執(zhí)行文件,除了glibc外沒(méi)有其他外部依賴。這讓部署變得異常方便:目標(biāo)機(jī)器上只需要一個(gè)基礎(chǔ)的系統(tǒng)和必要的管理、監(jiān)控工具,完全不需要操心應(yīng)用所需的各種包、庫(kù)的依賴關(guān)系,大大減輕了維護(hù)的負(fù)擔(dān)。這和Python有著巨大的區(qū)別。由于歷史的原因,Python的部署工具生態(tài)相當(dāng)混亂【比如setuptools,distutils,pip,

buildout的不同適用場(chǎng)合以及兼容性問(wèn)題】。官方PyPI源又經(jīng)常出問(wèn)題,需要搭建私有鏡像,而維護(hù)這個(gè)鏡像又要花費(fèi)不少時(shí)間和精力。

并發(fā)性好。Goroutine和channel使得編寫高并發(fā)的服務(wù)端軟件變得相當(dāng)容易,很多情況下完全不需要考慮鎖機(jī)制以及由此帶來(lái)的各種問(wèn)題。單個(gè)Go應(yīng)用也能有效的利用多個(gè)CPU核,并行執(zhí)行的性能好。這和Python也是天壤之比。多線程和多進(jìn)程的服務(wù)端程序編寫起來(lái)并不簡(jiǎn)單,而且由于全局鎖GIL的原因,多線程的Python程序并不能有效利用多核,只能用多進(jìn)程的方式部署;如果用標(biāo)準(zhǔn)庫(kù)里的multiprocessing包又會(huì)對(duì)監(jiān)控和管理造成不少的挑戰(zhàn)【我們用的supervisor管理進(jìn)程,對(duì)fork支持不好】。部署Python應(yīng)用的時(shí)候通常是每個(gè)CPU核部署一個(gè)應(yīng)用,這會(huì)造成不少資源的浪費(fèi),比如假設(shè)某個(gè)Python應(yīng)用啟動(dòng)后需要占用100MB內(nèi)存,而服務(wù)器有32個(gè)CPU核,那么留一個(gè)核給系統(tǒng)、運(yùn)行31個(gè)應(yīng)用副本就要浪費(fèi)3GB的內(nèi)存資源。

良好的語(yǔ)言設(shè)計(jì)。從學(xué)術(shù)的角度講Go語(yǔ)言其實(shí)非常平庸,不支持許多高級(jí)的語(yǔ)言特性;但從工程的角度講,Go的設(shè)計(jì)是非常優(yōu)秀的:規(guī)范足夠簡(jiǎn)單靈活,有其他語(yǔ)言基礎(chǔ)的程序員都能迅速上手。更重要的是Go自帶完善的工具鏈,大大提高了團(tuán)隊(duì)協(xié)作的一致性。比如gofmt自動(dòng)排版Go代碼,很大程度上杜絕了不同人寫的代碼排版風(fēng)格不一致的問(wèn)題。把編輯器配置成在編輯存檔的時(shí)候自動(dòng)運(yùn)行g(shù)ofmt,這樣在編寫代碼的時(shí)候可以隨意擺放位置,存檔的時(shí)候自動(dòng)變成正確排版的代碼。此外還有g(shù)ofix,

govet等非常有用的工具。

執(zhí)行性能好。雖然不如C和Java,但通常比原生Python應(yīng)用還是高一個(gè)數(shù)量級(jí)的,適合編寫一些瓶頸業(yè)務(wù)。內(nèi)存占用也非常省。

Go 優(yōu)雅退出實(shí)現(xiàn)方法 amp; context原理

1.通過(guò)endless包實(shí)現(xiàn)

2.通過(guò)shutdown實(shí)現(xiàn)

在go 1.8.x后,golang在http里加入了shutdown方法,用來(lái)控制優(yōu)雅退出。什么是優(yōu)雅退出? 簡(jiǎn)單說(shuō)就是不處理新請(qǐng)求,但是會(huì)處理正在進(jìn)行的請(qǐng)求,把舊請(qǐng)求都處理完,也就是都response之后,那么就退出。

shutdown通過(guò)context上下文實(shí)現(xiàn) 。

社區(qū)里不少http graceful動(dòng)態(tài)重啟,平滑重啟的庫(kù),大多是基于http.shutdown做的。平滑啟動(dòng)的原理很簡(jiǎn)單,fork子進(jìn)程,繼承l(wèi)isten fd, 老進(jìn)程優(yōu)雅退出。

3.context原理

context 是 Go 并發(fā)編程中常用到一種編程模式。

在并發(fā)程序中,由于超時(shí)、取消操作或者一些異常情況,往往需要進(jìn)行搶占操作或者中斷后續(xù)操作。熟悉 channel 的朋友應(yīng)該都見(jiàn)過(guò)使用 done channel 來(lái)處理此類問(wèn)題。比如以下這個(gè)例子:

上述例子中定義了一個(gè) buffer 為0的 channel done , 子協(xié)程運(yùn)行著定時(shí)任務(wù)。如果主協(xié)程需要在某個(gè)時(shí)刻發(fā)送消息通知子協(xié)程中斷任務(wù)退出,那么就可以讓子協(xié)程監(jiān)聽(tīng)這個(gè) done channel ,一旦主協(xié)程關(guān)閉 done channel ,那么子協(xié)程就可以推出了,這樣就實(shí)現(xiàn)了主協(xié)程通知子協(xié)程的需求。這很好,但是這也是有限的。

如果我們可以在簡(jiǎn)單的通知上附加傳遞額外的信息來(lái)控制取消:為什么取消,或者有一個(gè)它必須要完成的最終期限,更或者有多個(gè)取消選項(xiàng),我們需要根據(jù)額外的信息來(lái)判斷選擇執(zhí)行哪個(gè)取消選項(xiàng)。

考慮下面這種情況:假如主協(xié)程中有多個(gè)任務(wù)1, 2, …m,主協(xié)程對(duì)這些任務(wù)有超時(shí)控制;而其中任務(wù)1又有多個(gè)子任務(wù)1, 2, …n,任務(wù)1對(duì)這些子任務(wù)也有自己的超時(shí)控制,那么這些子任務(wù)既要感知主協(xié)程的取消信號(hào),也需要感知任務(wù)1的取消信號(hào)。

如果還是使用 done channel 的用法,我們需要定義兩個(gè) done channel ,子任務(wù)們需要同時(shí)監(jiān)聽(tīng)這兩個(gè) done channel 。嗯,這樣其實(shí)好像也還行哈。但是如果層級(jí)更深,如果這些子任務(wù)還有子任務(wù),那么使用 done channel 的方式將會(huì)變得非常繁瑣且混亂。

我們需要一種優(yōu)雅的方案來(lái)實(shí)現(xiàn)這樣一種機(jī)制:

這個(gè)時(shí)候 context 就派上用場(chǎng)了。

我們首先看看 context 的結(jié)構(gòu)設(shè)計(jì)和實(shí)現(xiàn)原理。

先看 Context 接口結(jié)構(gòu),看起來(lái)非常簡(jiǎn)單。

Context 接口包含四個(gè)方法:

可以看到 Done 方法返回的 channel 正是用來(lái)傳遞結(jié)束信號(hào)以搶占并中斷當(dāng)前任務(wù); Deadline 方法指示一段時(shí)間后當(dāng)前 goroutine 是否會(huì)被取消;以及一個(gè) Err 方法,來(lái)解釋 goroutine 被取消的原因;而 Value 則用于獲取特定于當(dāng)前任務(wù)樹(shù)的額外信息。而 context 所包含的額外信息鍵值對(duì)是如何存儲(chǔ)的呢?其實(shí)可以想象一顆樹(shù),樹(shù)的每個(gè)節(jié)點(diǎn)可能攜帶一組鍵值對(duì),如果當(dāng)前節(jié)點(diǎn)上無(wú)法找到 key 所對(duì)應(yīng)的值,就會(huì)向上去父節(jié)點(diǎn)里找,直到根節(jié)點(diǎn),具體后面會(huì)說(shuō)到。

emptyCtx 是一個(gè) int 類型的變量,但實(shí)現(xiàn)了 context 的接口。 emptyCtx 沒(méi)有超時(shí)時(shí)間,不能取消,也不能存儲(chǔ)任何額外信息,所以 emptyCtx 用來(lái)作為 context 樹(shù)的根節(jié)點(diǎn)。

但我們一般不會(huì)直接使用 emptyCtx ,而是使用由 emptyCtx 實(shí)例化的兩個(gè)變量,分別可以通過(guò)調(diào)用 Background 和 TODO 方法得到,但這兩個(gè) context 在實(shí)現(xiàn)上是一樣的。那么 Background 和 TODO 方法得到的 context 有什么區(qū)別呢?可以看一下官方的解釋:

Background 和 TODO 只是用于不同場(chǎng)景下:

Background 通常被用于主函數(shù)、初始化以及測(cè)試中,作為一個(gè)頂層的 context ,也就是說(shuō)一般我們創(chuàng)建的 context 都是基于 Background ;

而 TODO 是在不確定使用什么 context 的時(shí)候才會(huì)使用。

下面將介紹兩種不同功能的基礎(chǔ) context 類型: valueCtx 和 cancelCtx 。

valueCtx 利用一個(gè) Context 類型的變量來(lái)表示父節(jié)點(diǎn) context ,所以當(dāng)前 context 繼承了父 context 的所有信息; valueCtx 類型還攜帶一組鍵值對(duì),也就是說(shuō)這種 context 可以攜帶額外的信息。 valueCtx 實(shí)現(xiàn)了 Value 方法,用以在 context 鏈路上獲取 key 對(duì)應(yīng)的值,如果當(dāng)前 context 上不存在需要的 key ,會(huì)沿著 context 鏈向上尋找 key 對(duì)應(yīng)的值,直到根節(jié)點(diǎn)。

WithValue 用以向 context 添加鍵值對(duì):

這里添加鍵值對(duì)不是在原 context 結(jié)構(gòu)體上直接添加,而是以此 context 作為父節(jié)點(diǎn),重新創(chuàng)建一個(gè)新的 valueCtx 子節(jié)點(diǎn),將鍵值對(duì)添加在子節(jié)點(diǎn)上,由此形成一條 context 鏈。獲取 value 的過(guò)程就是在這條 context 鏈上由尾部上前搜尋:

跟 valueCtx 類似, cancelCtx 中也有一個(gè) context 變量作為父節(jié)點(diǎn);變量 done 表示一個(gè) channel ,用來(lái)表示傳遞關(guān)閉信號(hào); children 表示一個(gè) map ,存儲(chǔ)了當(dāng)前 context 節(jié)點(diǎn)下的子節(jié)點(diǎn); err 用于存儲(chǔ)錯(cuò)誤信息表示任務(wù)結(jié)束的原因。

再來(lái)看一下 cancelCtx 實(shí)現(xiàn)的方法:

可以發(fā)現(xiàn) cancelCtx 類型變量其實(shí)也是 canceler 類型,因?yàn)? cancelCtx 實(shí)現(xiàn)了 canceler 接口。 Done 方法和 Err 方法沒(méi)必要說(shuō)了, cancelCtx 類型的 context 在調(diào)用 cancel 方法時(shí)會(huì)設(shè)置取消原因,將 done channel 設(shè)置為一個(gè)關(guān)閉 channel 或者關(guān)閉 channel ,然后將子節(jié)點(diǎn) context 依次取消,如果有需要還會(huì)將當(dāng)前節(jié)點(diǎn)從父節(jié)點(diǎn)上移除。

WithCancel 函數(shù)用來(lái)創(chuàng)建一個(gè)可取消的 context ,即 cancelCtx 類型的 context 。 WithCancel 返回一個(gè) context 和一個(gè) CancelFunc ,調(diào)用 CancelFunc 即可觸發(fā) cancel 操作。直接看源碼:

之前說(shuō)到 cancelCtx 取消時(shí),會(huì)將后代節(jié)點(diǎn)中所有的 cancelCtx 都取消, propagateCancel 即用來(lái)建立當(dāng)前節(jié)點(diǎn)與祖先節(jié)點(diǎn)這個(gè)取消關(guān)聯(lián)邏輯。

這里或許有個(gè)疑問(wèn),為什么是祖先節(jié)點(diǎn)而不是父節(jié)點(diǎn)?這是因?yàn)楫?dāng)前 context 鏈可能是這樣的:

當(dāng)前 cancelCtx 的父節(jié)點(diǎn) context 并不是一個(gè)可取消的 context ,也就沒(méi)法記錄 children 。

timerCtx 是一種基于 cancelCtx 的 context 類型,從字面上就能看出,這是一種可以定時(shí)取消的 context 。

timerCtx 內(nèi)部使用 cancelCtx 實(shí)現(xiàn)取消,另外使用定時(shí)器 timer 和過(guò)期時(shí)間 deadline 實(shí)現(xiàn)定時(shí)取消的功能。 timerCtx 在調(diào)用 cancel 方法,會(huì)先將內(nèi)部的 cancelCtx 取消,如果需要?jiǎng)t將自己從 cancelCtx 祖先節(jié)點(diǎn)上移除,最后取消計(jì)時(shí)器。

WithDeadline 返回一個(gè)基于 parent 的可取消的 context ,并且其過(guò)期時(shí)間 deadline 不晚于所設(shè)置時(shí)間 d 。

與 WithDeadline 類似, WithTimeout 也是創(chuàng)建一個(gè)定時(shí)取消的 context ,只不過(guò) WithDeadline 是接收一個(gè)過(guò)期時(shí)間點(diǎn),而 WithTimeout 接收一個(gè)相對(duì)當(dāng)前時(shí)間的過(guò)期時(shí)長(zhǎng) timeout :

首先使用 context 實(shí)現(xiàn)文章開(kāi)頭 done channel 的例子來(lái)示范一下如何更優(yōu)雅實(shí)現(xiàn)協(xié)程間取消信號(hào)的同步:

這個(gè)例子中,只要讓子線程監(jiān)聽(tīng)主線程傳入的 ctx ,一旦 ctx.Done() 返回空 channel ,子線程即可取消執(zhí)行任務(wù)。但這個(gè)例子還無(wú)法展現(xiàn) context 的傳遞取消信息的強(qiáng)大優(yōu)勢(shì)。

閱讀過(guò) net/http 包源碼的朋友可能注意到在實(shí)現(xiàn) http server 時(shí)就用到了 context , 下面簡(jiǎn)單分析一下。

1、首先 Server 在開(kāi)啟服務(wù)時(shí)會(huì)創(chuàng)建一個(gè) valueCtx ,存儲(chǔ)了 server 的相關(guān)信息,之后每建立一條連接就會(huì)開(kāi)啟一個(gè)協(xié)程,并攜帶此 valueCtx 。

2、建立連接之后會(huì)基于傳入的 context 創(chuàng)建一個(gè) valueCtx 用于存儲(chǔ)本地地址信息,之后在此基礎(chǔ)上又創(chuàng)建了一個(gè) cancelCtx ,然后開(kāi)始從當(dāng)前連接中讀取網(wǎng)絡(luò)請(qǐng)求,每當(dāng)讀取到一個(gè)請(qǐng)求則會(huì)將該 cancelCtx 傳入,用以傳遞取消信號(hào)。一旦連接斷開(kāi),即可發(fā)送取消信號(hào),取消所有進(jìn)行中的網(wǎng)絡(luò)請(qǐng)求。

3、讀取到請(qǐng)求之后,會(huì)再次基于傳入的 context 創(chuàng)建新的 cancelCtx ,并設(shè)置到當(dāng)前請(qǐng)求對(duì)象 req 上,同時(shí)生成的 response 對(duì)象中 cancelCtx 保存了當(dāng)前 context 取消方法。

這樣處理的目的主要有以下幾點(diǎn):

在整個(gè) server 處理流程中,使用了一條 context 鏈貫穿 Server 、 Connection 、 Request ,不僅將上游的信息共享給下游任務(wù),同時(shí)實(shí)現(xiàn)了上游可發(fā)送取消信號(hào)取消所有下游任務(wù),而下游任務(wù)自行取消不會(huì)影響上游任務(wù)。

context 主要用于父子任務(wù)之間的同步取消信號(hào),本質(zhì)上是一種協(xié)程調(diào)度的方式 。另外在使用 context 時(shí)有兩點(diǎn)值得注意:上游任務(wù)僅僅使用 context 通知下游任務(wù)不再需要,但不會(huì)直接干涉和中斷下游任務(wù)的執(zhí)行,由下游任務(wù)自行決定后續(xù)的處理操作,也就是說(shuō) context 的取消操作是無(wú)侵入的; context 是線程安全的,因?yàn)? context 本身是不可變的( immutable ),因此可以放心地在多個(gè)協(xié)程中傳遞使用。

go中使用cmd與cron

/bin/bash -c "ls -l"

cmd-golang-pipe

pipe()創(chuàng)建2個(gè)文件描述符,fd[0]可讀,fd[1]可寫

fork() 創(chuàng)建子進(jìn)程 fd[1]被繼承到子進(jìn)程

dup2() 重定向子進(jìn)程 stdout/stderr到fd[1]

exec() 在當(dāng)前進(jìn)程內(nèi),加載并執(zhí)行二進(jìn)制程序

模擬一下cmd調(diào)用

模擬調(diào)用cmd時(shí),殺死bash進(jìn)程

go開(kāi)源Cronexpr庫(kù)

Parse() 解析與校驗(yàn)Cron表達(dá)式

Next() 根據(jù)當(dāng)前時(shí)間,計(jì)算下一次調(diào)度時(shí)間

模擬一下cron調(diào)用

執(zhí)行結(jié)果

模擬多個(gè)cron調(diào)用

執(zhí)行結(jié)果

golang 進(jìn)程創(chuàng)建,fork,以及熱重啟(無(wú)縫升級(jí))

一般來(lái)說(shuō),進(jìn)程的操作使用的是一些系統(tǒng)的命令,所以go內(nèi)部使用os包,進(jìn)行一些運(yùn)行系統(tǒng)命令的操作

os 包及其子包 os/exec 提供了創(chuàng)建進(jìn)程的方法。

一般的,應(yīng)該優(yōu)先使用 os/exec 包。因?yàn)?os/exec 包依賴 os 包中關(guān)鍵創(chuàng)建進(jìn)程的 API,為了便于理解,我們先探討 os 包中和進(jìn)程相關(guān)的部分。

Unix :fork創(chuàng)建一個(gè)進(jìn)程,(及其一些變種,如 vfork、clone)。

Go:Linux 下創(chuàng)建進(jìn)程使用的系統(tǒng)調(diào)用是 clone。

允許一進(jìn)程(父進(jìn)程)創(chuàng)建一新進(jìn)程(子進(jìn)程)。具體做法是,新的子進(jìn)程幾近于對(duì)父進(jìn)程的翻版:子進(jìn)程獲得父進(jìn)程的棧、數(shù)據(jù)段、堆和執(zhí)行文本段的拷貝??蓪⒋艘暈榘迅高M(jìn)程一分為二。

終止一進(jìn)程,將進(jìn)程占用的所有資源(內(nèi)存、文件描述符等)歸還內(nèi)核,交其進(jìn)行再次分配。參數(shù) status 為一整型變量,表示進(jìn)程的退出狀態(tài)。父進(jìn)程可使用系統(tǒng)調(diào)用 wait() 來(lái)獲取該狀態(tài)。

目的有二:其一,如果子進(jìn)程尚未調(diào)用 exit() 終止,那么 wait 會(huì)掛起父進(jìn)程直至子進(jìn)程終止;其二,子進(jìn)程的終止?fàn)顟B(tài)通過(guò) wait 的 status 參數(shù)返回。

加載一個(gè)新程序(路徑名為 pathname,參數(shù)列表為 argv,環(huán)境變量列表為 envp)到當(dāng)前進(jìn)程的內(nèi)存。這將丟棄現(xiàn)存的程序文本段,并為新程序重新創(chuàng)建棧、數(shù)據(jù)段以及堆。通常將這一動(dòng)作稱為執(zhí)行一個(gè)新程序。

沒(méi)有直接提供 fork 系統(tǒng)調(diào)用的封裝,而是將 fork 和 execve 合二為一,提供了 syscall.ForkExec。如果想只調(diào)用 fork,得自己通過(guò) syscall.Syscall(syscall.SYS_FORK, 0, 0, 0) 實(shí)現(xiàn)。

os.Process 存儲(chǔ)了通過(guò) StartProcess 創(chuàng)建的進(jìn)程的相關(guān)信息。

一般通過(guò) StartProcess 創(chuàng)建 Process 的實(shí)例,函數(shù)聲明如下:

它使用提供的程序名、命令行參數(shù)、屬性開(kāi)始一個(gè)新進(jìn)程。StartProcess 是一個(gè)低級(jí)別的接口。os/exec 包提供了高級(jí)別的接口,一般應(yīng)該盡量使用 os/exec 包。如果出錯(cuò),錯(cuò)誤的類型會(huì)是 *PathError。

屬性定義如下:

FindProcess 可以通過(guò) pid 查找一個(gè)運(yùn)行中的進(jìn)程。該函數(shù)返回的 Process 對(duì)象可以用于獲取關(guān)于底層操作系統(tǒng)進(jìn)程的信息。在 Unix 系統(tǒng)中,此函數(shù)總是成功,即使 pid 對(duì)應(yīng)的進(jìn)程不存在。

Process 提供了四個(gè)方法:Kill、Signal、Wait 和 Release。其中 Kill 和 Signal 跟信號(hào)相關(guān),而 Kill 實(shí)際上就是調(diào)用 Signal,發(fā)送了 SIGKILL 信號(hào),強(qiáng)制進(jìn)程退出,關(guān)于信號(hào),后續(xù)章節(jié)會(huì)專門講解。

Release 方法用于釋放 Process 對(duì)象相關(guān)的資源,以便將來(lái)可以被再使用。該方法只有在確定沒(méi)有調(diào)用 Wait 時(shí)才需要調(diào)用。Unix 中,該方法的內(nèi)部實(shí)現(xiàn)只是將 Process 的 pid 置為 -1。

通過(guò) os 包可以做到運(yùn)行外部命令,如前面的例子。不過(guò),Go 標(biāo)準(zhǔn)庫(kù)為我們封裝了更好用的包: os/exec,運(yùn)行外部命令,應(yīng)該優(yōu)先使用它,它包裝了 os.StartProcess 函數(shù)以便更容易的重定向標(biāo)準(zhǔn)輸入和輸出,使用管道連接 I/O,以及作其它的一些調(diào)整。

exec.LookPath 函數(shù)在 PATH 指定目錄中搜索可執(zhí)行程序,如 file 中有 /,則只在當(dāng)前目錄搜索。該函數(shù)返回完整路徑或相對(duì)于當(dāng)前路徑的一個(gè)相對(duì)路徑。

func LookPath(file string) (string, error)

如果在 PATH 中沒(méi)有找到可執(zhí)行文件,則返回 exec.ErrNotFound。

Cmd 結(jié)構(gòu)代表一個(gè)正在準(zhǔn)備或者在執(zhí)行中的外部命令,調(diào)用了 Run、Output 或 CombinedOutput 后,Cmd 實(shí)例不能被重用。

一般的,應(yīng)該通過(guò) exec.Command 函數(shù)產(chǎn)生 Cmd 實(shí)例:

用法

得到 * Cmd 實(shí)例后,接下來(lái)一般有兩種寫法:

前面講到,通過(guò) Cmd 實(shí)例后,有兩種方式運(yùn)行命令。有時(shí)候,我們不只是簡(jiǎn)單的運(yùn)行命令,還希望能控制命令的輸入和輸出。通過(guò)上面的 API 介紹,控制輸入輸出有幾種方法:

參考資料:

如何在 Go 語(yǔ)言中使用 Redis 連接池

一、關(guān)于連接池

一個(gè)數(shù)據(jù)庫(kù)服務(wù)器只擁有有限的資源,并且如果你沒(méi)有充分使用這些資源,你可以通過(guò)使用更多的連接來(lái)提高吞吐量。一旦所有的資源都在使用,那么你就不 能通過(guò)增加更多的連接來(lái)提高吞吐量。事實(shí)上,吞吐量在連接負(fù)載較大時(shí)就開(kāi)始下降了。通??梢酝ㄟ^(guò)限制與可用的資源相匹配的數(shù)據(jù)庫(kù)連接的數(shù)量來(lái)提高延遲和吞 吐量。

如何在Go語(yǔ)言中使用Redis連接池

如果不使用連接池,那么,每次傳輸數(shù)據(jù),我們都需要進(jìn)行創(chuàng)建連接,收發(fā)數(shù)據(jù),關(guān)閉連接。在并發(fā)量不高的場(chǎng)景,基本上不會(huì)有什么問(wèn)題,一旦并發(fā)量上去了,那么,一般就會(huì)遇到下面幾個(gè)常見(jiàn)問(wèn)題:

性能普遍上不去

CPU 大量資源被系統(tǒng)消耗

網(wǎng)絡(luò)一旦抖動(dòng),會(huì)有大量 TIME_WAIT 產(chǎn)生,不得不定期重啟服務(wù)或定期重啟機(jī)器

服務(wù)器工作不穩(wěn)定,QPS 忽高忽低

要想解決這些問(wèn)題,我們就要用到連接池了。連接池的思路很簡(jiǎn)單,在初始化時(shí),創(chuàng)建一定數(shù)量的連接,先把所有長(zhǎng)連接存起來(lái),然后,誰(shuí)需要使用,從這里取走,干完活立馬放回來(lái)。 如果請(qǐng)求數(shù)超出連接池容量,那么就排隊(duì)等待、退化成短連接或者直接丟棄掉。

二、使用連接池遇到的坑

最近在一個(gè)項(xiàng)目中,需要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 Web Server 提供 Redis 的 HTTP interface,提供 JSON 形式的返回結(jié)果??紤]用 Go 來(lái)實(shí)現(xiàn)。

首先,去看一下 Redis 官方推薦的 Go Redis driver。官方 Star 的項(xiàng)目有兩個(gè):Radix.v2 和 Redigo。經(jīng)過(guò)簡(jiǎn)單的比較后,選擇了更加輕量級(jí)和實(shí)現(xiàn)更加優(yōu)雅的 Radix.v2。

Radix.v2 包是根據(jù)功能劃分成一個(gè)個(gè)的 sub package,每一個(gè) sub package 在一個(gè)獨(dú)立的子目錄中,結(jié)構(gòu)非常清晰。我的項(xiàng)目中會(huì)用到的 sub package 有 redis 和 pool。

由于我想讓這種被 fork 的進(jìn)程最好簡(jiǎn)單點(diǎn),做的事情單一一些,所以,在沒(méi)有深入去看 Radix.v2 的 pool 的實(shí)現(xiàn)之前,我選擇了自己實(shí)現(xiàn)一個(gè) Redis pool。(這里,就不貼代碼了。后來(lái)發(fā)現(xiàn)自己實(shí)現(xiàn)的 Redis pool 與 Radix.v2 實(shí)現(xiàn)的 Redis pool 的原理是一樣的,都是基于 channel 實(shí)現(xiàn)的, 遇到的問(wèn)題也是一樣的。)

不過(guò)在測(cè)試過(guò)程中,發(fā)現(xiàn)了一個(gè)詭異的問(wèn)題。在請(qǐng)求過(guò)程中經(jīng)常會(huì)報(bào) EOF 錯(cuò)誤。而且是概率性出現(xiàn),一會(huì)有問(wèn)題,一會(huì)又好了。通過(guò)反復(fù)的測(cè)試,發(fā)現(xiàn) bug 是有規(guī)律的,當(dāng)程序空閑一會(huì)后,再進(jìn)行連續(xù)請(qǐng)求,會(huì)發(fā)生3次失敗,然后之后的請(qǐng)求都能成功,而我的連接池大小設(shè)置的是3。再進(jìn)一步分析,程序空閑300秒 后,再請(qǐng)求就會(huì)失敗,發(fā)現(xiàn)我的 Redis server 配置了 timeout 300,至此,問(wèn)題就清楚了。是連接超時(shí) Redis server 主動(dòng)斷開(kāi)了連接??蛻舳诉@邊從一個(gè)超時(shí)的連接請(qǐng)求就會(huì)得到 EOF 錯(cuò)誤。

然后我看了一下 Radix.v2 的 pool 包的源碼,發(fā)現(xiàn)這個(gè)庫(kù)本身并沒(méi)有檢測(cè)壞的連接,并替換為新server{location/pool{content_by_lua_block{localredis=require"resty.redis"localred=redis:new()localok,err=red:connect("127.0.0.1",6379)ifnotokthenngx.say("failedtoconnect:",err)returnendok,err=red:set("hello","world")ifnotokthenreturnendred:set_keepalive(10000,100)}}}

發(fā)現(xiàn)有個(gè) set_keepalive 的方法,查了一下官方文檔,方法的原型是 syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size) 貌似 max_idle_timeout 這個(gè)參數(shù),就是我們所缺少的東西,然后進(jìn)一步跟蹤源碼,看看里面是怎么保證連接有效的。

function_M.set_keepalive(self,...)localsock=self.sockifnotsockthenreturnnil,"notinitialized"endifself.subscribedthenreturnnil,"subscribedstate"endreturnsock:setkeepalive(...)end

至此,已經(jīng)清楚了,使用了 tcp 的 keepalive 心跳機(jī)制。

于是,通過(guò)與 Radix.v2 的作者一些討論,選擇自己在 redis 這層使用心跳機(jī)制,來(lái)解決這個(gè)問(wèn)題。

四、最后的解決方案

在創(chuàng)建連接池之后,起一個(gè) goroutine,每隔一段 idleTime 發(fā)送一個(gè) PING 到 Redis server。其中,idleTime 略小于 Redis server 的 timeout 配置。連接池初始化部分代碼如下:

p,err:=pool.New("tcp",u.Host,concurrency)errHndlr(err)gofunc(){for{p.Cmd("PING")time.Sleep(idelTime*time.Second)}}()

使用 redis 傳輸數(shù)據(jù)部分代碼如下:

funcredisDo(p*pool.Pool,cmdstring,args...interface{})(reply*redis.Resp,errerror){reply=p.Cmd(cmd,args...)iferr=reply.Err;err!=nil{iferr!=io.EOF{Fatal.Println("redis",cmd,args,"erris",err)}}return}

其中,Radix.v2 連接池內(nèi)部進(jìn)行了連接池內(nèi)連接的獲取和放回,代碼如下:

//Cmdautomaticallygetsoneclientfromthepool,executesthegivencommand//(returningitsresult),andputstheclientbackinthepoolfunc(p*Pool)Cmd(cmdstring,args...interface{})*redis.Resp{c,err:=p.Get()iferr!=nil{returnredis.NewResp(err)}deferp.Put(c)returnc.Cmd(cmd,args...)}

這樣,我們就有了 keepalive 的機(jī)制,不會(huì)出現(xiàn) timeout 的連接了,從 redis 連接池里面取出的連接都是可用的連接了??此坪?jiǎn)單的代碼,卻完美的解決了連接池里面超時(shí)連接的問(wèn)題。同時(shí),就算 Redis server 重啟等情況,也能保證連接自動(dòng)重連。

網(wǎng)頁(yè)題目:go語(yǔ)言fork進(jìn)程 go go for
本文地址:http://aaarwkj.com/article4/docpiie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、面包屑導(dǎo)航、網(wǎng)站策劃、品牌網(wǎng)站制作、企業(yè)建站、手機(jī)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站
国产午夜福利一区在线| 日韩亚洲欧美另类精品| 精品久久久久久亚洲电影| 亚洲第六页亚洲第一页| 日本韩国国产三级在线| 伊人色综合久久天天五月婷| 中文有码人妻字幕在线| 亚洲综合中文字幕日韩| 人妻勾引中文字幕在线视频| 尤物在线观看视频播放| 成人深夜免费观看视频| 99精品国产综合久久麻豆| 日韩精品少妇一区二区| 亚洲日本精品免费在线观看| 最新日韩精品电影在线网| 99久久免费精品老色| 欧美日韩一区二区综合性色| 精品欧美熟妇高潮喷水特黄| 99热在线精品国产观看| 91极品气质女神长腿翘臀| 国产日韩欧美视频在线观看| 国产激情福利一区二区| 福利1中文字幕手机在线| 免费在线观看97视频| 亚洲熟乱熟女一区二区| 亚洲ve中文字幕久久一区二区 | 欧美大片在线观看高清| 99蜜桃臀成人美女视频| 尤物欧美精品一区二区三区 | 最新日本免费久久精品| 在线观看免费完整观看一区二区| 亚洲伦理av在线观看| 狠狠综爱五月天的婷婷| 日韩国产精品视频二区| 国产av剧情在线免费观看| 欧美国产成人精品一区| 亚洲天堂人妻一区二区| 日本国产一区二区三区在线观看| 国产精品久久久久大屁股精品性色| 黄色av链接在线观看| 少妇人妻系列中文在线|