技術分享|Rust技術分享:Quic 傳輸協議開發實踐

TinTinLand
5粉絲
4 次觀看·2024年10月15日
Rust嘮嗑室由TinTinLand和Rust.CC共同倡導,定期每月舉行的線上活動。聚焦于實用案例分享、編程技巧傳授,邀請Rust開發大咖與主持人共同分享最新應用案例和編程心得,同時呈現Rust領域的最新動態和資訊。不僅如此,在線聽眾更可融入討論,共同促進Rust社區的發展與交流。
📱歡迎添加小T微信號(ID:TinTin-land)加入技術社區,和我們一起交流吧。
🧑🏫 分享嘉賓:sky, gm-quic 核心開發者
📖 分享大綱:
1. 項目簡介
2. Quic 協議介紹
3. 開發實踐
———————————————————
🏠 關注渠道
1️⃣ Discord: https://discord.gg/kmPnTDSFu8
2️⃣ Twitter: https://twitter.com/OurTinTinLand
3️⃣ Medium: https://medium.com/@tintin.land2021
4️⃣ YouTube: https://www.youtube.com/channel/UCfHiMcFt-4btbC75FsReQh
大家好,我是主持人Tracy
咱們又到了這個月的樂客室了
咱們這個RUS樂客室是由天嵐和RUSCC共同創的
定期每月舉行的一個線上活動
居就於十萬裏增享編程解鎖傳授
邀請咱們RUS老師來介紹一下心得
然後會投稿一下一些新聞
最重要的其實是最後大家一塊兒嘮個課
然後大家有什麼都可以暢談關於RUS的
然後再口播一下
我們這個天嵐是浮能線下載開發者
通過GDP輸送開發者到開放網絡的
大家感興趣可以掃碼天天小踢了解一下
然後咱們今天可能很多同學看到這個海報了
咱們邀請到了Sky老師
Sky老師進行分享之後
然後快速回顧一下新聞
然後最後Mike老師帶着大家一起嘮課
或者一會兒大家有什麼疑問
對於Sky老師分享內容
大家以後最後的時候都可以嘮了
但Mike老師今天很有可能並不能上線
因爲在這個時差問題
然後Mike老師昨天晚上一直在趕一個項目
對行
那話不多說
那就交給咱們Sky老師吧
老師您可以這個分享屏幕了
看到了嗎
可以的老師
那分享就開始
大家晚上好
我是來自劍元科技的Sky
今天分享的主題是
使用Rust開發Quick傳輸協議的一些經驗和心得
本次分享分爲三個部分
首先先介紹一下項目背景
介紹一下我們項目QnQuick的由來
第二部分是介紹Quick傳輸協議
由於Quick十分複雜
本次分享重點介紹的是Quick握手的細節
最後是我們使用Rust開發Quick的一些實踐經驗
首先進入第一部分
我們知道互聯網是從只讀的Web1網絡
發展到Web2的可讀可寫網絡
在Web2的網絡中
我們將個人的數據傳輸到平臺
平臺再進行處理和展示
現在大部分的應用的形態都是這樣
我們的個人數據是由平臺管理的
我們劍元科技關注的是下一代互聯網技術
特別是將數據主權還於用戶
以後我們每個人的設備都可以是服務器
比如將隱私數據存儲在個人的設備上面
平臺或者其他用戶訪問
需要向我們的設備發起請求
然後可以最小化的授權我們的隱私數據
Quick因爲其低延遲
安全多路複用等特性
是構建網絡的重要基礎設施
Rust的許多特性
比如說內存安全高性能
亦不正是我們需要的
我們用Rust實現了GenQuick這個項目
後面在實踐篇會詳細介紹
接下來進入第二部分Quick簡介
相信大部分人可能多多少少
對Quick都有一些瞭解
比如說低延遲建立連接
消除對頭阻塞安全等等
就是PPT左邊寫的這些
PPT右邊的圖
展示了Quick在網絡五層模型中的位置
可以看到Quick底層是使用UDP
並且融合了TLS協議
代替的是TCP加TLS的位置
TLS爲Quick提供了安全性
Quick爲TLS提供了可靠傳輸通道
這個可靠傳輸的含義很豐富
包括ASK確認機制
用色控制算法
留的多路複用流控等等
我們今天重點介紹的是前兩個優勢
就是快速建立連接和安全的特性
接下來介紹的是Quick的握手
上圖是TCP加TLS握手的流程圖
先看TCP這一邊
TCP的三次握手相信大家都很熟悉了
主要的目的是確認雙方的讀寫能力
和確認初始報號
防止歷史連接等等
TCP三次握手完成之後
會進行一次TLS握手
TLS握手的主要目的是交換密鑰證書認證
Quick將TLS握手融合到了它自己的握手之中
這樣就節省下了TLS握手的1RTT
實際上TLS1.3也提供了0RTT握手
所以TCP加TLS1.3握手
需要的是兩個RTT或者一個RTT
Quick握手和TLS握手融合
就只需要一個RTT或者0RTT
這就是Quick快速建立連接的一個根本原因
就是它融合了TLS握手
節省了一個RTT
我們先簡單看一下TLS的握手流程
先看PPT右邊這張圖
這張圖來自TLS1.3的RFC
握手的流程大概分爲三個階段
第一個是密鑰交換階段
這個階段主要是協商加密算法
以及共享密鑰的信息
這個階段完成之後
所有的信息都需要加密
所有的握手消息都需要加密
第二個階段是服務參數
服務端參數交換階段是協商其他握手參數
最後一個階段是認證階段
協商雙方認證密鑰
確認以及握手報文的交易
接下來看左下角這個圖
它展示了TLS的分層
上層是Handshake層
它的功能主要是密鑰交換
協商認證和加密參數
下層是Record層
它的主要功能就是加密保護
上層的Handshake層依賴的是
Record層來進行加密
而Record層加密的密鑰
也是來自於Handshake層
所以這兩個層其實可以說是互相依賴的
所以一開始可以看到密鑰交換階段
可以看作是不加密的
當server接收到Client Hello消息之後
纔有了Handshake密鑰
然後此後都用這個密鑰進行加密
可以看到握手的加密密鑰
是用大括號框起來的部分
然後後面應用數據的加密
其實是用中括號加起來
擴起來的
它這裏有一個密鑰升級的過程
Quick的握手後面也有類似的流程
左下角這個圖還有一個重點沒有畫
就是TLS層其實是依賴於底層的可靠傳輸的
也就是說Record層接收到的
所有數據都是有序的
後面我們會重點講Record層
這個和Quick的加密比較相關
我們來看Record層是如何加密數據的
它使用的是AAD加密
需要的有四個輸入
一個是密鑰
這個密鑰是通過Handshake層
雙方協商生成的
第二個是Nonce
這個Nonce是一個隨機值
每次加密不同
可以防止重犯攻擊
雖然它說是雖然它叫Nonce
但是它其實並不是完全隨機的
因爲一個數據包加解密
需要同時輸入一個Nonce才能解密
因此這個Nonce值
它應該是收發雙方可預測的
所以一般用遞增的序號和一個
出子向量易獲來生成
第三個輸入就是帶加密的數據
或者是帶解密的數據
第四個輸入是關聯數據
一般是頭部數據用於驗證完整性的
我們先看一下TCP和TLS
TCP和TLS是分層的
TCP先進行三次握手
建立了可靠傳輸通道之後
再進行TLS握手
TLS就可以依賴
TCP建立起的可靠傳輸通道
所以TCP的頭部其實是不加密的
RECORD層收到的數據
是TCP整理好的數據
所以TLS可以輕鬆的
利用TCP的包序號包號來生成這個nonce值
對於Quick來說情況就複雜多了
Quick的可靠傳輸是靠
Packet Number和Offset來實現的
就是收到數據之後
可能要通過對這個Packet Number
進行排序來進行有序交付
這裏就出現了一個死鎖
它不同於TCP
它這個Packet Number它也是加密的
所以不解密就沒辦法獲取Packet Number
如果不獲取Packet Number
就沒辦法有序的交付給TLS層
這個問題的解決辦法其實也很簡單
就是兩階段加密
這裏要補充一下Quick包的結構
Quick包分爲包頭和負載兩個部分
先看左邊的這部分
左邊的部分畫了兩個包頭
有長包頭和短包頭
與TLS協議類似
Quick握手也要協商一些東西
長包頭多出來的東西就是
Quick握手的時候需要協商的
可以看這個長包頭裏面有什麼
看這個DCID它指的是目的連接ID
再補充一個點就是連接ID
Quick它標誌一條連接
其實是用一對連接ID來表示的
而不是TCP的4元組
這樣做的目的主要是爲了能夠實現連接遷移
當我們IP端口發生改變時
就無需重新握手
只需要連接ID不變就可以
路由道對應的連接
比如說我們在高鐵上
基站快速切換的時候
我們的IP會切換的
如果是TCP的話
可能需要重新進行握手
但是對Quick來說
它就可以沿用之前的連接
這主要CID這部分
主要是長包頭多出來的部分
然後當握手完成之後
其實就不需要協商這些東西
就只需要填一個目的的連接ID
就可以路由道目的的Quick連接
右邊這個連接的圖
灰色的部分是加密的數據
可以看到加密的數據
主要是加密了Hacking的Number
還有第一字節的一些比特位
主要是RR是保留字段
PP這個是主要是Hacking的Number的長度
總的來說主要加密的還是Hacking的Number
接下來我們看Quick包的加密流程
剛剛說到AAD它需要有四個輸入
我們這裏是將包頭和負載分開加入的
這四個輸入分別是key
就是密鑰
這個是Handshake層獲得到的
nonce值是一個初始項量和一個
從明文的包頭裏面取出來的
Packet Number進行易獲得到的
還有就是Packet的負載
然後再輸入Packet的Header
作爲額外的數據用作校驗
就可以得到加密後的負載
我們從加密的負載抽出一部分Sample
再和這個HeaderKey進行加密
得到一個Mask研碼
就可以對這個Packet的Header進行加密
解密的流程相反是先解密頭部
先用加密的Sample和HeaderKey來得到Mask
來解密包頭
然後包頭中取出Packet Number
就可以得到nonce
然後再把這四段輸入進AAD中
就可以輸出負載的明文
OK
剛剛看了加密的流程
現在看Quick握手的具體流程
先看這個下面的圖裏有三個方框
Quick將包的空間分爲三個
Initial,Handshake和Data空間
不同的空間使用不同的包號和密鑰
其中Data空間有兩種密鑰
一種是0RTT密鑰
一種是1RTT密鑰
我們再看上面的握手流程
Client發起握手的時候
第一個Client Hello
是用Initial密鑰進行加密的
這個Initial密鑰它Python字
剛剛說的目的CID字段
它是客戶端隨機生成的
所以這個字段是不加密的
所以可以看成就是這個Initial包
它其實是不安全的
是不加密的
當Server收到這個包之後
就可以通過這個包來生成
接下來需要的Handshake密鑰和1RTT密鑰
並返回Server Hello
這個流程和剛剛介紹的TLS握手流程是比較像的
此時Server有了Handshake密鑰和1RTT密鑰
這時候它就可以回數據包
這裏可以看到有一個密鑰升級的過程
就是Initial密鑰升級成Handshake密鑰
再最後升級成1RTT密鑰
這個和TLS握手也是類似的
TLS握手也有一個密鑰升級的過程
還有一個點是
如果客戶端在之前的繪畫中保存了0RTT密鑰
它在握手時候就可以將這個0RTT包攜帶過去
在實現0RTT握手
就是在第一個包就可以請求Server的數據
這裏還有和TCP不同的一個點是
下個階段的數據包是可能是提前到達的
因爲此時還沒有建立起可靠的傳輸
當Server回覆Handshake包時
就是這個Handshake和1RTT包
它可能是同時回覆的
而且不在同一個UDP包中
Client可能會先接收到1RTT包
再接收到Handshake包
所以此時Client可能是沒有1RTT密鑰的
所以這個包是不能被解密的
需要緩存下來
這是實現的時候也需要考慮的一個細節
通過上面的PPT可以看到
Quick的握手是比TCP要複雜的
所以爲了融合TLS握手
但是又不破壞Quick
就是不需要在Quick裏面實現TLS
RFC-19001規定了Quick和TLS的一些交互形式
先看右上角這個圖
可以看到Quick其實是替代了
剛剛TLS的Record層和一個TCP的可靠傳輸層
所以Quick其實是爲TLS提供了抽象的可靠流
TLS通過Quick來收發消息
這裏的重點是TLS這個模塊本身並沒有數據的收發能力
它只能生成比如說Client Hello來交給Quick
Quick再將其封裝到CryptoStream中
然後再用TLS提供的Initial密鑰進行加密
然後發送出去
收包也是逆過來的流程
先用TLS提供的密鑰進行解密
然後再寫到加密流中
最後寫到TLS站裏面
右下角這個圖就展示了Quick和TLS的交互流程
前面講Quick的包結構的時候
有提到Quick的連接是由一對連接ID組成的
在握手期間還有協商連接ID的作用
協商連接ID的邏輯比較簡單
它的核心是目的連接ID
也就是DCID是由數據包的接收方選擇的
用於提供一致的路由
原連接ID是由自己發起方來決定的
可以看左邊這個圖的例子
當客戶端第一次發起請求時候
它的原連接ID是自己填的CE
DCID它是不知道是什麼
是隨機生成的一個SE
然後Server收到這個數據包之後
它就可以在SCID上填上自己選擇的CID S3
返回給客戶端
客戶端在收到這個包之後
後續的所有的包的DCID都只能填這個S3
這樣就完成了一次簡單的連接ID的協商過程
右邊這個圖是加入了一個retry包的流程
其實也是一樣的
只是Server在第一次收到initial包之後
讓客戶端重試
並且選擇了一個連接ID S2
客戶端在重試的時候
要使用這個連接ID進行重試
S2
Server在回initial包的時候
可以再次替換這個連接ID改成S3
然後後續握手完成之後
Client發給Server的所有的數據包的CID
都要填上這個S3
除了TLS握手使用密鑰保護數據包之外
Quick的握手還有一個攻擊需要防範的
就是放大攻擊
上圖所示
攻擊者A他可以向Server發一個initial包和一個0RTT包
並且在IP的包頭改掉
IP數據包改掉原地址
指向受害者
在這個0RTT包中可能是一個http請求
這個請求是
這個請求是請求大量的數據
Server收到這個包之後
因爲這個0RTT包
請求了大量數據
Server可能會在沒有驗證這個客戶端的身份的時候
就向這個受害者發送大量的數據
這樣的話
攻擊者就以極低的代價向受害者發起了DOS攻擊
這種攻擊叫做放大攻擊
因爲他以一個0RTT包的數據的一個極低的代價
放大了許多倍的數據量來攻擊受害者
然後有了放大攻擊就有抗放大攻擊
這個防放大攻擊的核心
其實就是要驗證發送方是否擁有他實際聲明的地址
在驗證通過之前
不要向其發送超過三倍
接收到數據量三倍的數據
就是說
攻擊者向服務端發送了1000字節的數據
當沒有驗證這個地址之前
服務端只能最多返回3000字節的數據
這樣的話就有效的限制了這個放大攻擊的倍數
最多隻能放大三倍
那麼如何驗證對端是否擁有其聲明的地址呢
其核心就是對方能夠接收到我的數據
並且能根據我的數據進行返回
TWIK的握手其實提供了影視驗證
我們其實不需要做任何額外的事情
就可以驗證對方的地址
先看左邊這張圖
對於客戶端來說
當成功的解密了服務端的英語首包的時候
他就驗證了服務端的地址
因爲服務端的英語首密鑰是
剛剛說了是派生自客戶端
是客戶端隨機生成的一個DCID的字段
同樣的服務端如果能夠解密到handshake
客戶端發來的handshake包同樣驗證了客戶端的地址
因爲這個handshake的密鑰是派生自英語首密鑰
裏面攜帶的server hello的內容
所以這個是在握手的過程中
自然而然的就驗證了對方地址
就叫解密即驗證
第二個例子是使用token驗證
解密驗證雖然簡單
但是它有一個弊端就是
它驗證需要一個RTT
在某些場景下可能會比較慢
比如說直播的場景下
我零RTT建立起了連接
需要你馬上返回直播數據
但是你需要驗證我的地址就慢了一個RTT
會影響起步速度
所以Quick提供了另外一種驗證方式
就是使用token驗證
服務端可以提前向客戶端頒發token
下次客戶端連接的時候
就可以在initial包中攜帶token
服務端只要驗證token
是不是自己之前頒發過的
就可以馬上進行驗證
在此時就可以向客戶端返回大量的數據
還有一種是服務端用retry包進行驗證
retry包也可以攜帶token
這樣的話
下次客戶端發起initial連接的時候
帶上retry包的token也同樣可以進行驗證
我們上面簡單介紹了Quick的握手流程
可以看到Quick的握手
其實完成了許多的任務
密鑰生成地址驗證
參數的傳輸協商連接ID
它是比TCP握手要複雜很多的
然後也有其他任務
可能會需要依賴握手的結果
比如說發包
它需要對應的密鑰和連接ID
才能把包發出去
下面我們來講實踐中
如何設計出優雅高效的組件
來解決這個錯綜複雜的邏輯
這個圖是QM Quick的整體架構圖
一個簡單的傳輸層
已經沒法描述Quick的複雜性了
今天我們重點講的是加解密這一層
Quick的握手就是實現在這一層
分層的好處就是功能結合
每一層都有獨立的功能
層與層之間就可以通過接口
或者管道進行通信即可
我們剛剛有提到
Quick和TLS握手的交互
其實就是TLS從Quick讀數據
處理完數據之後再返回
如果有密鑰升級的話
再返回密鑰升級
我們在實現的時候用了REST TLS這個庫
下面這個代碼
可以看read handshake這個接口
這個接口是TLS庫從Quick來讀數據
write handshake是TLS往Quick寫數據
並且返回是否有密鑰升級
可以看到這兩個接口其實都很簡單
而且是同步的
但是網絡的收發實際上是異步的
我要從Quick模塊讀取數據
但是我其實不知道什麼時候
Quick模塊有數據可讀
這裏就涉及到了Quick的異步流
和TLS讀寫的結合
我們採用的方案就是異步的讀寫分離
先看上面這個圖
我們用一個reader和writer來包裝了同一個TLS section
這個TLS section實際上是用Arc Mutex包裹起來的
這樣的話這個TLS section就可以在多線程中
自由的複製和使用
這個TLS section具有和REST TLS這個模塊讀寫交互的能力
再看下面代碼的部分
我們首先用Tokyo Swarm起一個異步任務
這個任務它的功能很簡單
就是循環的讀取數據
在這個任務裏面循環調用TLS的WriteHS來讀取TLS數據
當然因爲從TLS讀取數據的接口是同步的
我們用一個循環調用這個接口
看什麼時候有數據可讀
這樣可能會佔滿CPU
所以我們將這個封裝成了一個異步組件
使用.await來從TLS讀取數據
如果有數據的話
就會從.await返回ready
沒數據的話就會一直在這掛起pending
讀出數據之後
我們會將這個數據寫到cryptostream中加密流中
這個過程也是異步的
同時可以看TLS有沒有密鑰升級來返回
如果有密鑰升級
並同時將這個密鑰設置到這個handshake key中
那麼我們是怎麼實現將同步的調用封裝成異步調用呢
Rust給我們提供了一個future這個tray
只要結構實現了這個tray
異步執行器就會自動的去幫你執行這個任務
就完成了從同步到異步的轉換
可以看這個結構
每次pool都會調用TLS的writehs這個接口
就是第10行這一段
看有沒有數據可以讀
如果沒有數據可以讀
就複製一份context waker
並且返回pending
這樣上層還是會阻塞在剛剛點await的地方
等待下次pool
如果有數據的話就可以直接返回數據
此次的異步任務就到此結束
那麼問題就是如果阻塞在了點await這裏
什麼時候會再次pool這個任務
什麼時候會再次喚醒呢
我們先放下這個問題
先看寫數據
因爲讀可讀其實是依賴可寫的數據
先看網TLS寫數據的流程
首先先從加密流中異步的讀取數據
這個方法的實現也是類似的
也是實現future
如果有數據就返回ready
然後將
然後如果從加密流中讀到了數據
就調用readhs將這部分數據寫到TLS中
寫入之後
再調用TLS的once read的接口
來看看TLS是不是有數據可以讀
如果有數據可讀就調用
就調用TLS的點await
來喚醒剛剛的那個reader的任務
這樣就實現了
這樣就實現了異步喚醒reader的任務
這裏使用這裏使用兩個獨立的
tokyo的異步任務就實現了讀寫的結構
他們可以相互配合
這裏還有一個細節就是readhs
其實不需要異步封裝
因爲他這個異步任務的流程是阻塞
在加密流的讀取中
這裏已經異步來阻塞了
如果有數據可讀就可以馬上寫給TLS
而不用像從TLS讀數據一樣
要封裝成一個異步的接口
剛剛展示的從TLS讀數據
還有一個細節
密鑰升級的時候調用了key的setkeys
這裏也涉及到一個異步任務
密鑰是有狀態的
我們利用了raster媒體的特性
在不同的狀態下
密鑰是具有不同的屬性的
當密鑰是pending的時候
它應該有的數據是
異步等待密鑰這個任務的waker
當密鑰就緒的時候
擁有的其實是實際的密鑰
當密鑰廢棄的時候
就不再擁有任何的數據
調用setkeys意味着密鑰的狀態發生了轉換
並且可以喚醒waker了
所以狀態機其實也很適合用在異步任務
可以看右邊的代碼
調用setkeys的時候會檢查密鑰的狀態
如果是pending的話
它會將waker拿出來
調用waker來喚醒
正在等待的異步任務
並且將自己的狀態替換成ready
將新的密鑰設置進去
如果是其他兩種狀態的話
其實都是不合法的
就是我的密鑰已經ready了
或者是我空間的密鑰已經被廢棄了
就不應該再設置新的密鑰了
這裏是一個收包的流程
當收包的時候其實是依賴空間密鑰的狀態的
所以需要異步的等待
每次破的時候是檢查密鑰的狀態
就緒即可返回密鑰
類似的可以看代碼的第三行
是表示這個garry most keys這個結構
它是一個簡單keys
mark keys結構的封裝
它每次破就會檢查這個keys的狀態
如果是pending的話
就會複製一份正在等待異步任務的waker
然後返回pending
如果是ready狀態的話
就可以馬上的返回密鑰
如果是invalid的話
其實也是就緒的
然後這個密鑰是空
就就表示這個空間已經被廢棄了
就不需要就不需要再解密這個空間的數據了
嗯看20行這裏
是這個tokyo throne出來的是一個收包的任務
我們從異步的我們從收包的對立裏面讀出
讀出一個數據包
然後然後調用keys
gary most keys這個這個接口來看
我們是否有這個空間的密鑰
如果有密鑰的話
我們就可以進行繼續的密鑰解密
如果沒有密鑰的話會阻塞在這
或者返回none的話
就結束就可以結束這個空間的讀包任務
嗯之前我們講呃在握手的過程中
其實包可能是會會亂續到達的
比如我沒有ertt密鑰的時候收到收到ertt包
呃我們用這種異步的方法就可以完美的解決剛剛的問題
如果收到了一個沒有密鑰的數據包
我們會直接異步的點await來點await阻塞在解密這裏
這樣的話就收包的任務就會非常的獨立
只需要關心密鑰的狀態
我不需要關心什麼tls握手是什麼進展
或者是我嘗試從tls讀取密鑰
這樣就太偶合了
這樣的話就極大的降低了收包時候的複雜度
嗯這一個個這一個個小小的異步任務就像齒輪一樣
串聯起來了quick錯綜複雜的邏輯
我們可以仔細分析每個任務的依賴關係可以將異步化
就可以讓代碼看起來非常的簡短和通順
每個這個tokyo sprung出來的任務
其實都非常的簡短
邏輯也非常清晰
發包就相對簡單一些
如果某個空間的密鑰沒有準備好就直接跳過即可
這裏和收包邏輯的主要區別就是發包
其實並沒有先並沒有從發送流中先讀取數據
而是先判斷了密鑰的狀態
如果這個密鑰沒有準備好
這個數據還保存在發送流中
下次可以再發收包
他需要馬上處理收到的加密包
或者你要把這個加密包緩存起來後續再處理
用異步等待就可以實現將數據包緩存在異步的狀態裏面
繼續執行的時候會繼續處理這個數據包
最後我們再介紹一個例子就是地址驗證
我們剛剛提到地址驗證是通過之前頒發的token進行驗證的
這就要求我們要緩存這個token
QnQuick的設計是提供接口讓用戶自行實現緩存的邏輯
對於客戶端來說實現token sync接口
來實現自定義token的存儲或者檢索邏輯
你可以將這個token存儲在文件中或者數據庫中
然後淘汰的邏輯也由你自己實現
對於服務端來說提供token provider這個接口
用戶就可以實現token的生成和驗證機制
這兩個接口在創建QnQuick client
或者QnQuick server的時候就可以設置進去
這樣後續就不需要再關心我是如何地址驗證的了
以上就是今天分享的內容
我們在實現QnQuick的過程中用到了很多RAS的特性
這些特性其實幫助我們能夠高效安全地實現QnQuick的複雜功能
特別是它的異步編程
還有train併發工具這些來保證了我們能安全高效的實現
今天只分享了QnQuick握手的部分
這個其實是QnQuick很小的一個模塊
QnQuick協議其實還有很多有趣的細節值得我們關注
感興趣的朋友可以加入我們的QnQuick交流羣
後續我們還會把其他我們實現QnQuick所採購的坑
或者認識到QnQuick的一些細節進行一系列的分享
謝謝大家
本次分享就到這
好
感謝Sky老師
那我就先把這個新聞快速過一下
現在切到我這個屏幕
新聞快速過一下
如果大家有什麼疑問
大家就再聊會兒
這回就摘了四個新聞
第一個是Docker
是個現代化快速和用戶友好的Docker口段
它是一個簡化DNS系統上的一個容器管理的這麼一個工具
然後它是用Rust、Torrent和RackJS構建的
也有一個界面
然後還有一個就是它可以處理這個Docker容器
就非常簡單
對
也有各種主題
一些日日查看
包括內部終端容器管理
容器狀態等等一些監控
對
然後它現在是目前也是隻支持這個Linux系統
然後未來是打算要拓展到這個Windows和這個macOS
對
老師的PPT是可以分享的
這個一會兒大家有什麼疑問
對
你們可以先掃碼
添加這個小題
然後我們有一個這個Rust羣
可以把這個老師邀請到羣裏
把PPT給大家分享一下
對
然後對
然後這個Docker對
未來也是要拓展到這個Windows和macOS
然後第二個這個新聞的這個Spread for Hub Goblin
是這個其實它是一個Minecraft的這個升設計比賽的一個獲獎作品
它其實就是
可以在Minecraft地圖中生成一個就是比較有意思的一個定居點
它跟很多這個靜態村莊實例不同
它生成器會模擬這個村莊的一個建造過程
然後在Minecraft裏就是重放這個過程
而且不需要任何這個模組或者外部程序
對
它是Rust編寫的
大家感興趣可以去看一下
對
它不是用這個HTTP接口
然後第三個是這個Arnis
它其實也是這個Minecraft的一個相當於一個地圖
它可以根據這個OpenStreetMap的地圖
也是Rust編寫的
它這個地理空間數據
然後在這個Minecraft的Java版本中
就是生成這個現實世界等任何的選定的位置
比如說這個牆壁啊
建築物
噴泉
農田等等
這個座標節點
對
然後還可以自動獲取這個數據
然後進行解析排序
生成這個Minecraft的世界
對
然後大家感興趣也可以去玩玩
對
然後最後一個呢
是這個FGEL
它是一個可嵌入的一個建制村莊引擎
然後它有一些特點
我都列在這了
然後它其實不是一個這個獨立的服務器關於數據庫
它對這個建制大橋有一定的限制
然後它內部同步也是可以支持這個獨顯城訪問
而且提供了這個永久性控制等等功能
也是使用這個穩定的一個磁盤格式
可以提供這個遷移路徑
然後
大家有什麼
疑問啊
大家可以先掃這個小助手
我還有很多這個精彩活動
什麼疑問也可以先聊聊
給大家幾分鐘的時間
老師
您可以查看這個聊天框啊
有一個同學提了一個問題啊
就是這個CMQV是部署如何做到負載均衡的
這個負載均衡
其實就是Quick的RFC裏面有規定一個叫PreferredAdjust的這個傳輸參數
或者是你用CID也可以實現負載均衡
就是你部署在前端的服務器
你可以通過CID來轉發連接到後端的服務器
或者用PreferredAdjust在第一次連接
不知道有沒有注意到可以返回retry
在這個retry裏面可以選擇
可以攜帶一個PreferredAdjust
讓客戶端來連接服務端指定的一個地址來實現負載均衡
咱們有個同學還想再聊聊
行
麥克老師昨天睡得比較晚
在趕項目
所以今天可能不帶大家聊天了
大家有什麼想聊的可以在自發聊聊
再給個三秒鐘的時間
行
那估計沒有什麼想聊
大家想聊就是在掃這個小助手的密碼進羣裏
然後包括剛纔問的這些QE的同學
我們會把老師邀請到羣裏
咱們再交流
這還有一個問題
老師這個和Cloudflare的實現
Cloudflare實現的
其實是一個同步的raster的實現
我們這個是純異步的
剛剛重點其實也是在介紹異步的實現
我們把Quick的一個個小小小的功能來拆成一個個異步的組件
這些組件互相配合就可以實現複雜的邏輯
如果是全部純同步的話
整個邏輯會融合在一起
會非常的複雜
這個和QuickNN也是類似的
QuickNN它是用底層的一個driver來驅動整個Quick所有的事件
超時事件或者是收包事件來驅動整個協議
不像我們是拆分了很多一個異步任務reactor
然後用相互調用wake這種方式來實現
對
擁塞控制我們後面可能還會繼續有分享
這裏我們事先實現了BBR和Reno的擁塞控制
擁塞控制是一個比較大的話題
可能今天簡短的也沒辦法詳細的介紹到
我可以簡單介紹一下BBR的一些
這個還是比較多
可以關注我們下次分享
還可以和老師再約下次再約一次分享
大家有什麼感興趣的話題也可以告訴我們
然後我們可以幫助大家對接一片老師
要不然大家沒有什麼疑問
咱們就先到這
然後這個視頻也會上傳到B站和YouTube
沒來得及的同學也可以再看回放
大家關注小助手
我們還有很多精彩活動
請期待
咱們就下期再見
感謝Sky老師
感謝各位同學
拜拜
謝謝大家
拜拜
