golang是特別不適合拿來做應用程式層可靠協議開發的語言。所有的可靠協議都依賴於串連狀態,在講究並發的情境下,所有的狀態都依賴於事件,所有的事件都依賴於核心檔案描述符,問題是,在可靠情境下,我們常常需要將一個連接埠用作一塊網卡,一塊網卡可以有65536個描述符並發處理事件,一個連接埠卻只有一個描述符,這一個描述符需要類比出65536個描述符的事件處理效能,這本來就是令人頭大的問題。golang本身的協程機制----固然golang和大多數的協程實現不盡一致----導致每一個事件的處理都應短暫,且事件之間應是無狀態的,如果對於可靠協議各階段的業務與事件理解不到位,極其容易實現出資源有餘,而協議效能低下的情況。
為什麼要有上面一段呢?因為目前的Sia,IPFS,Storj,Swarm都是golang實現的,這些實現都是在應用程式層實現基於udp的可靠傳輸協議,做到點對點資料存放區與共用,問題是,我猜測這些項目,包括現在的所有區塊鏈項目,都缺乏網路傳輸專家的加持,所以他們的傳輸實現顯得非常荒謬。講真,網路傳輸是靠時間積累的東西,TCP發展了半個多世紀,才發展出BBR,更不用說二十年不到,大多數時候處於鬆散研究狀態的去中心化傳輸。從BT開始到幾個已經ICO大大筆美刀的儲存項目,在傳輸上,可以說都處於簡單粗暴的狀態,更不用說與現有網路的親和策略。
IPFS事實上就是一個BT協議,而BT的底層是uTP。uTP在傳輸上實現了AIMD,這是從傳統TCP繼承的東西,經典而有用。順便說一句,TCP網路本身是一個混沌系統,發送方與接收方都不知道網路的狀態,他們既不知道是否能繼續發送,也不知道收不到是否合理,唯一能做的就是試探,所以大神們都說TCP是一個控制系統,而不是傳輸協議。然而,AIMD會導致網路的輕微擁塞,從單條鏈路看,網路總是處於將丟包而未丟包處。問題是在封包交換網路中,物理鏈路是被分時複用的,單條鏈路能探測到的擁塞點,在多條鏈路時,可能已經產生極大丟包。所以單條鏈路探測的AIMD總是不準確的。因此,在IPFS上,對於時間不敏感的儲存、下載情境,大概無壓力,但如果涉及到流媒體傳輸,IPFS怕是力有未逮。
Storj的問題是什麼呢?Storj也使用了uTP,問題是,Storj也沒有搞懂AIMD,他們粗暴地設定了一個固定速率,這讓我簡直不知道怎麼評價他們的傳輸實現。Sia的實現並沒有使用uTP,Sia實現了自己的RateLimit,以此來控制報文發送的Pace Rate,問題是Sia的傳輸實現不是事件驅動的實現,他們使用了睡眠,然而睡眠的時候,串連是不能感知鏈路的變化的,因此發送端對於鏈路是否能繼續容納報文,是後知後覺的。
那麼,是不是這些存放裝置都不能用呢?恰恰相反,都能用,遺憾的是,也僅止於能用,如果想用他們來實現其他更加高效的傳輸,無異於癡人說夢。講到底,這些東西都不過是TCP在應用程式層的重新實現,而現在所有的重新實現都還處在TCP最早期的階段而已。TCP最早期的階段甚至沒有擁塞控制,大家都可勁兒使用鏈路,直到某天,有位大神注意到他的報文經常不能按照預期抵達,於是提出了擁塞理論。半個世紀後,擁塞控制演算法逐漸成熟----其實離成熟還很遠----我們才能在有很多人搗亂的網路上享受流暢的傳輸服務。然而偉大的TCP也自有缺點:逾時重傳實在是不準確而又浪費頻寬,RTT又實在測不準,於是才出現了一系列的補救措施,形成擁塞控制這一整套的特定技術。
IPFS提出要做去中心化網路基礎設施,但從技術架構上來看,實在是不足夠,然而做一個去中心化的儲存設施卻綽綽有餘。相較於大陸某幾家專註於做應用甚至於連應用都沒有做好的廠商----沒錯,不要心虛,我說的就是你們----IPFS從概念上算是挺有創新的項目了。