C語言分布式系統中的進程標識_第1頁
C語言分布式系統中的進程標識_第2頁
C語言分布式系統中的進程標識_第3頁
C語言分布式系統中的進程標識_第4頁
C語言分布式系統中的進程標識_第5頁
已閱讀5頁,還剩3頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

本文格式為Word版,下載可任意編輯——C語言分布式系統中的進程標識C語言分布式系統中的進程標識

如何為一個程序每次運行的進程取一個唯一標識符。也就是說,httpd程序第一次運行,進程是httpd_1,它原地重啟了,進程是httpd_2。下面是我為大家探尋整理的C語言分布式系統中的進程標識,夢想大家能有所收獲,更多精彩內容請實時關注我們我!

"進程process'是操作系統的兩大根本概念之一,指的是在內存中運行的程序。在日常交流中,"進程'這個詞通常不止這一個意思。有時候我們會說"httpd進程'或者"mysqld進程',指的其實是program,而不確定是特指某一個"進程'某一次fork系統調用的產物。一個"httpd進程'重啟了,它還是"一個httpd進程'。本文議論的是,如何為一個程序每次運行的進程取一個唯一標識符。也就是說,httpd程序第一次運行,進程是httpd_1,它原地重啟了,進程是httpd_2。

本文所指的"進程標識符'是用來唯一標識一個程序的"一次運行'的。每次啟動一個進程,這個進程理應被賦予一個唯一的標識符,與當前正在運行的全體進程都不同;不僅如此,它理應與歷史上曾經運行過,目前已消亡的進程也都不同這兩條的直接推論是,與將來可能運行的進程也都不同。"為每個進程命名'在分布式系統中有相當大的實際意義,更加是在考慮failover的時候。由于一個程序重啟之后的新進程和它的"前世進程'的狀態通常不一樣,只要與它打交道的其他進程s最好能通過它的進程標識符變更來很輕易地判斷該程序已經重啟,而采取必要的救災措施,防止搭錯話。

本文先假定每個服務端程序的端口是靜態調配的,在公司內部有一個公用wiki來記錄端口和程序的對應關系然后通過NIS或DNS發布。譬如端口11211始終對應memcached,其他程序不會使用11211端口;3306始終留給mysqld;3690始終留給svnserve。在分布式系統的初級階段,這是通常的做法;到了高級階段,多半會用動態調配端口號,由于端口號只有6萬多個,是稀缺資源,在公司內部也有調配完的一天。本文只考慮TCP協議,不考慮UDP協議,"端口'都指的是TCP端口。

另外,我們假定在一臺機器上,一個listeningport同時只能由一個進程使用,不考慮古老的listen+fork模型多個進程可以accept同一個端口上進來的連接,關于這點陳碩已經寫的好多,見《Linux新增系統調用的啟示》《多線程服務器的適用場合》。

錯誤做法

在分布式系統中,如何指涉referto某一個進程呢,或者說一個進程如何取得自己的全局標識符以下簡稱gpid?輕易想到的有兩種做法:

*ip:portport是這個進程對外供給網絡服務的端口號,一般就是它的'tcplisteningport

*host:pid

而這兩種做法都有問題。為什么?

假設進程本身是無狀態的,或者重啟了也沒有關系,那么用ip:port來標識一個"服務'是沒問題的,譬如常見的httpd和memcached都可以用它們的慣用port80和11211來標識。我們可以在其他程序里安好地引用referto"運行在:80的那個http服務器',或者":11211的memcached',就算這兩個service重啟了,也不會有太惡劣的后果,大不了客戶端重試一下,或者自動切換到備用地址。

假設服務是有狀態的,那么ip:port這種標識方法就有大問題,由于客戶端無法區分從頭到尾和自己打交道的是一個進程還是先后多個進程。在開發服務端程序的時候,為了能快速重啟,我們一般都會設置SO_REUSEADDR,這樣的結果是前一秒鐘站在:8888后面的進程和后一秒鐘占據:8888的進程可能不一致服務端程序快速重啟了。

比方說,考慮一個類似GFS的分布式文件系統的master,假設它僅以ip:port來標識自己,然后它向shadows不是chunkserver下達同步指令,那么shadows如何得知master是不是已經重啟呢?發指令的是master的"前世'還是"今生'?是不是理應拒絕"前世'的遺命?

假設考慮改成host:pid這種標識方式會不會好一點?我認為換湯不換藥,由于pid的狀態空間很小,重復的概率對比大。譬如Linux的pid的最大值是32768/proc/sys/kernel/pid_max,一個程序重啟之后,獲得與"前世'一致pid的概率是1/32768。或許有讀者不相信重啟之后pid會重復,由于pid是遞增的,遇到上限再回到目前空閑的最小pid。考慮一個服務端程序A,它的pid是1234,它已經穩定運行了好幾天,這期間,pid已經增長了幾個輪回由于這臺機器時常會啟動一些scripts執行一些輔佐工作。在A崩潰的前一刻,最近被使用的pid已經回到了1232,當A崩潰之后,某個守護進程啟動一個腳本pid=1233來清理A的log,然后再重啟A程序;這樣一來,重啟之后的A程序的pid碰巧和它的前世一致,都是1234。也就是說,用host:pid不能唯一標識進程。

那么合在一起,用ip:port:pid呢?也不能做到唯一。它和host:pid面臨的問題是一樣的,由于ip:port這片面在重啟之后不會變,pid可能輪回。

我猜這時有人會想,建一個中心服務器,特意調配系統的gpid好了,每個進程啟動的時候向它詢問自己的gpid。這錯得更遠:這個全局pid調配器的gpid由誰來定?如何保證它調配的gpid不重復考慮這個程序也可能意外重啟?它是不是成為系統的singlepointoffailure?假設要對該gpid調配器做容錯,是不是面臨分布式系統的根本問題:狀態遷移?

還有一種手段,用一個足夠強的隨機數做gpid,這樣一來切實不會重復,但是這個gpid本身也沒有多大額外的意義,不便于管理和維護比方說根據gpid找到是哪個機器上運行的哪個進程。

正確做法:以四元組ip:port:start_time:pid作為分布式系統中進程的gpid,其中start_time是64-bit整數,表示進程的啟動時刻UTC時區,muduo::Timestamp。理由如下:

*輕易保證唯一性。假設程序短時間重啟,那么兩個進程的pid必定不重復還沒有走完一個輪回:就算每秒創造1000個進程,也要30多秒才會輪回,而以這么高的速度創造進程的話,服務器已根本癱瘓了。;假設程序運行了相當長一段時間再重啟,那么兩次啟動的start_time必定不重復。見下文關于時間重復的解釋

*產生這種gpid的本金很低幾次低本金系統調用,沒有用到全局服務器,不存在singlepointoffailure。

*gpid本身有意義,根據gpid馬上就能知道是什么進程port,運行在哪臺機器ip,是什么時間啟動的,在/proc目次中的位置/proc/pid等,進程的資源使用處境也可以通過運行在那臺機器上的監控程序報告出來。

*gpid具有歷史意義,便于將來追溯。比方說進程crash,那么我知道它的gpid,就可以去歷史記錄中查詢它crash之前的cpu/mem負載有多大。

假設僅以ip:port:start_time作為gpid,那么不能保證唯一性,假設程序短時間重啟間隔一秒或幾秒,start_time可能會往回跳變NTP在調時間或暫停正好處于閏秒期間。關于時間跳變的問題留給下一篇博客《〈程序中的日期與時間〉其次章:計時與定時》,簡樸地說,計算機上的時鐘不確定是單調遞增的。

沒有port怎么辦?一般來說,一個網絡服務程序會偵聽某個端口來供給服務,假設它是個純粹的客戶端,只主動發起連接,沒有主動偵聽端口,gpid該如何調配呢?根據陳碩在《分布式系統的工程化開發方法》一文中的觀點"在程序里內置http服務器',分布式系統中的每個長期運行的、會與其他機器打交道的進程都理應供給一個管理接口,對外供給一個修理探查通道,可以查看進程的全部狀態。這個管理接口就是一個TCPserver,它會偵聽某個port。

使用這樣的修理通道的一個額外好處是,可以自動防止重復啟動程序。由于假設重復啟動,bind到那個運維port的時候會出錯端口已被占用,程序會馬上退出。更妙的是,不用惦記進程crash沒來得及清理鎖假設用跨進程的mutex就有這個風險,進程關閉的時候操作系統會自動把它開啟的port都關上,下一個進程可以順遂啟動。

進一步,還可以把程序的名稱和版本號作為gpid的一片面,這起到錦上添花的作用。

TCP協議的啟示

我在《分布式系統的工程化開發方法》中提到"從TCP協議能學到什么?',今天講的這個gpid其實也是由TCP協議啟發而來。TCP用ip:port來表示endpoint,兩個endpoint構成一個socket。這貌似符合一開頭提到的以ip:port來標識進程的做法。其實不然。在發起TCP連接的時候,為了防止前一次同樣地址的連接一致的local_ip:local_port:remote_ip:remote_port的干擾稱為wanderingduplicates,即流浪的packets,TCP協議使用seq號碼這種在SYNpacket里第一次發送的seq號碼稱為initialsequencenumber,ISN來區分本次連接和以往的連接。TCP的這種思路

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論