Socket.D 基于消息的响应式应用层网络协议
首先根據(jù) Socket.D 官網(wǎng)的副標(biāo)題,Socket.D 的自我定義是:
基于事件和語(yǔ)義消息流的網(wǎng)絡(luò)應(yīng)用協(xié)議。
官網(wǎng)定義的特點(diǎn)是:
- 基于事件,每個(gè)消息都可事件路由
- 所謂語(yǔ)義,通過元信息進(jìn)行語(yǔ)義描述
- 流關(guān)聯(lián)性,有相關(guān)的消息會(huì)串成一個(gè)流
- 語(yǔ)言無(wú)關(guān),使用二進(jìn)制輸傳數(shù)據(jù)(支持 tcp, ws, udp)。支持多語(yǔ)言、多平臺(tái)
- 斷線重連,自動(dòng)連接恢復(fù)
- 多路復(fù)用,一個(gè)連接便可允許多個(gè)請(qǐng)求和響應(yīng)消息同時(shí)運(yùn)行
- 雙向通訊,單鏈接雙向互聽互發(fā)
- 自動(dòng)分片,數(shù)據(jù)超出 16Mb,會(huì)自動(dòng)分片、自動(dòng)重組(udp 除外)
- 接口簡(jiǎn)單,是響應(yīng)式但用的是監(jiān)聽與回調(diào)風(fēng)格(經(jīng)典易用)
Socket.D 是基于這些特性需求誕生的一種新型響應(yīng)式網(wǎng)絡(luò)協(xié)議。Socket.D 借鑒了很多其他協(xié)議發(fā)展過程中遇到的問題,然后總結(jié)歸納進(jìn)自己的實(shí)踐當(dāng)中。
基于 Socket.D 的一些主要特性分別做一下介紹,并和 HTTP 之類的常見協(xié)議進(jìn)行比較:
- Destination (URL) 顯示連接地址
- Event 事件
- Multiplexed, Binary Protocol 多路復(fù)用的二進(jìn)制協(xié)議
- Bidirectional Streaming 雙向流
- Socket Resumption 連接恢復(fù)
- Message passing 消息傳遞模型
- Transport independent 與傳輸層解耦的應(yīng)用層協(xié)議
一、兩層路由能力
- path 路由能力
Socket.D 是基于顯示連接地址的,可以實(shí)現(xiàn)像 http 或 websocket 一樣的“頻道”路由的效果。地址例:
//模擬聊天場(chǎng)景的用戶地址
sd:tcp://127.0.0.1:8602
//模擬聊天場(chǎng)景的管理員地址
sd:tcp://127.0.0.1:8602/admin?u=admin&p=1234
- event 路由能力
Socket.D 每個(gè)消息都有事件描述,可以起到 path 或 topic 或 cmd 類似的路由效果。示例:
//模擬消息中間件的發(fā)布指令
client.send("event.mq.publish", new StringEvent("{userId:1}").metaSet("topic","demo"));
//模擬消息中間件的訂閱指令
client.send("event.mq.subscribe", new StringEvent("").metaSet("topic","demo"));
二、多路復(fù)用的二進(jìn)制協(xié)議
現(xiàn)在 Multiplexing,Asynchronous,Non-blocking I/O 已經(jīng)被說爛了,基本上就是標(biāo)配。這些特性意味著什么?拿HTTP的發(fā)展史感受一下:
從 HTTP1.0 到 HTTP3.0 在傳輸性能上的進(jìn)步
- 在 HTTP1.0 時(shí)代,每個(gè) HTTP request 都要新建一個(gè)網(wǎng)絡(luò)連接。網(wǎng)絡(luò)連接不能復(fù)用
- HTTP1.1 時(shí)代,一個(gè)網(wǎng)絡(luò)連接仍然在一個(gè)時(shí)候只能負(fù)責(zé)一個(gè) request,但是整個(gè) request/response 結(jié)束后連接可以得到復(fù)用。
- 會(huì)有文章講到 HTTP1.1 的核心是pipeline功能,是也不是。pipelining 支持一個(gè) TCP 連接上按照順序連續(xù)發(fā)送多個(gè) HTTP 請(qǐng)求而不需要等待前一個(gè)請(qǐng)求的響應(yīng),但是它同時(shí)要求HTTP response也要按照請(qǐng)求的順序逐個(gè)發(fā)送,這對(duì)服務(wù)器提出了很多要求,而且如果第一個(gè)響應(yīng)很慢會(huì)拖累所有的后續(xù)響應(yīng)(pipeling的隊(duì)頭阻塞),所以事實(shí)上并沒有得到多少運(yùn)用。即使到今天大部分瀏覽器仍然是默認(rèn)關(guān)閉HTTP pipelining功能的,所以說HTTP1.1的主要突破還只是連接復(fù)用。
- HTTP2.0 是個(gè)飛躍,開始支持 multiplexing,一個(gè)TCP連接上可以同時(shí)承載多個(gè)request/response,用這種方式替代1.1的pipelining提升HTTP的并行效果,也自然不存在什么隊(duì)頭阻塞了。每一個(gè)request/response的信息流,我們把它稱作一個(gè)HTTP stream。這個(gè)時(shí)候一個(gè)HTTP client對(duì)于一個(gè)origin,只需要建立一個(gè)TCP就夠了。(但是multiplexing帶來(lái)了新的問題)
- 現(xiàn)在HTTP3.0也差不多了。2.0解決了1.1pipelining的隊(duì)頭阻塞問題,但是卻無(wú)法解決TCP本身的隊(duì)頭阻塞。而因?yàn)門CP/IP在內(nèi)核協(xié)議棧中,簡(jiǎn)直無(wú)法升級(jí),于是HTTP選擇了QUIC作為新的傳輸層協(xié)議。 QUIC基于UDP,在用戶模式中實(shí)現(xiàn)了類似TCP的connection oriented的功能同時(shí)解決TCP的隊(duì)頭阻塞,自帶multiplexing等等。
所以,HTTP/2具有的優(yōu)點(diǎn),Socket.D 都有。另外,Socket.D 是一個(gè)二進(jìn)制協(xié)議,也就是說在一個(gè) Socket.D 連接上傳輸?shù)南Ⅲw對(duì)數(shù)據(jù)格式?jīng)]有任何要求,應(yīng)用程序可以為所欲為的壓縮數(shù)據(jù)量的大小。
這樣的二進(jìn)制協(xié)議通常來(lái)說能給性能帶來(lái)極大的提升,但是產(chǎn)生的代價(jià)是,網(wǎng)絡(luò)中間件也會(huì)因?yàn)闊o(wú)法解讀消息體中的數(shù)據(jù),喪失了在對(duì)具體應(yīng)用流量進(jìn)行監(jiān)控,日志和路由的能力。所以 Socket.D 通過把每個(gè)消息體分成 sid, event, data 和 metaString 的方式,在保證高效傳輸?shù)那疤嵯拢蔡峁┝吮┞对獢?shù)據(jù)給網(wǎng)絡(luò)中間件的能力(方便做語(yǔ)義處理),同時(shí)還能路由消息。
frame: {flag, message: {sid, event, entity: { metaString, data}}}
對(duì)于每個(gè) data,應(yīng)用可以采用不同的序列化方法。metaString 則采用標(biāo)準(zhǔn)的 url queryString 的通用格式(所有網(wǎng)絡(luò)中間件通用)。
- data 一般作為應(yīng)用本身需要傳遞的業(yè)務(wù)數(shù)據(jù),采取自定義的高效序列化方式,且對(duì)網(wǎng)絡(luò)基礎(chǔ)設(shè)施不可見
- metaString 采用標(biāo)準(zhǔn)的 url queryString 的通用格式。在分布式傳輸?shù)倪^程中,這些中間件可以按需求對(duì) metaString 進(jìn)行讀寫,然后調(diào)整路由。
三、雙向流
上面提到,HTTP這幾年在傳輸性能上進(jìn)步了很多。但說到底在應(yīng)用層仍然僅支持client request/server response的交互模型。
這里一些同學(xué)可能有疑問,比如:
那HTTP/2推出的Server Push是什么
HTTP2.0推出了一個(gè)新的Server Push功能,但這個(gè)功能通常只是用來(lái)提前將一些靜態(tài)資源返還給用戶而已。舉個(gè)例子:一個(gè)簡(jiǎn)單的網(wǎng)站有三個(gè)靜態(tài)資源組成: index.html, index.css, index.js。 我們打開瀏覽器打開index.html,就會(huì)發(fā)起一個(gè)HTTP request拿到index.html。在不使用server push的情況下,我們要等瀏覽器解析出index.css 和 index.js之后才會(huì)再次向服務(wù)器發(fā)起請(qǐng)求。而運(yùn)用server push,服務(wù)器可以根據(jù)一些規(guī)則預(yù)知到瀏覽器也需要index.css和index.js,并在客戶端發(fā)送新的請(qǐng)求之前直接推送給該客戶端。
所以,這個(gè)功能的使用場(chǎng)景非常有限,而且也不是一個(gè)真正雙向的交互模式。
結(jié)論:僅僅使用HTTP/2協(xié)議,不在其基礎(chǔ)之上再加一層其他協(xié)議的情況下是無(wú)法在應(yīng)用層實(shí)現(xiàn)雙向流的(比如,gRPC)。
回到交互模式,Socket.D 的幾種模式:
- Send
- SendAndRequest -> Reply
- SendAndSubscribe -> Stream Reply
- Reply
- ReplyEnd
- Session(雙向使用上面的發(fā)送與答復(fù))
通常來(lái)說,越復(fù)雜的交互模式,為了保存交互狀態(tài),就需要占用更多的內(nèi)存和計(jì)算資源。這也是為什么 Socket.D 會(huì)提供多種不同的 API。另外,當(dāng) Socket.D 的 client 和 server 建立了長(zhǎng)連接之后,任何一方都可以是 Requester 或是 Responder。服務(wù)器也可以扮演 Requester 的角色,首先發(fā)起 Request。
四、異步消息傳遞
Socket.D 還有另外一個(gè)非常重要的概念使之完全區(qū)分于類HTTP協(xié)議,那就是異步消息傳遞。
不同于HTTP當(dāng)中存在Request,Response。Socket.D在網(wǎng)絡(luò)傳輸上只有Frame這一個(gè)消息格式。有一個(gè)相同點(diǎn)是,類HTTP協(xié)議通常擁有一個(gè)顯式的destination (URL),使用起來(lái)會(huì)非常有親切感和簡(jiǎn)單。
如果Requester的 Socket.D 消息R首先通過了一個(gè)網(wǎng)絡(luò)中間件(Broker),那么請(qǐng)求者(Requester)并不關(guān)心該消息的最終目的地在哪里,網(wǎng)絡(luò)中間件可以全權(quán)負(fù)責(zé)路由模塊的實(shí)現(xiàn)。該架構(gòu)可以支持微服務(wù),也可以支持IOT場(chǎng)景,等等。
這種架構(gòu)很有意思,不僅能在微服務(wù)中加入streaming支持,還有如下特點(diǎn):
1.客戶端也可以暴露服務(wù)
由于 Socket.D 的雙向流特性,和Broker建立連接的客戶端即可以做Requester也可以做Responder,比如圖中的Device 1和Device 2雖然是移動(dòng)終端或者IOT設(shè)備,但仍然可以向其他設(shè)備或數(shù)據(jù)中心的主機(jī)提供服務(wù)
2.自動(dòng)服務(wù)注冊(cè)/發(fā)現(xiàn)
Socket.D 在成功建立連接時(shí)。如果該client想要暴露一個(gè)服務(wù),則在連接地址上給自己取個(gè)名字(就像加入一個(gè)社交群,讓別人能At到你)。連接成功建立之后,Socket.D Broker可以直接通過記錄網(wǎng)絡(luò)連接狀況來(lái)達(dá)到服務(wù)注冊(cè)和發(fā)現(xiàn)的效果。通過'@'參數(shù)取名示例:
sd:tcp://127.0.0.1:8602?@=demoapp
3.基于消息 metaString 實(shí)現(xiàn)請(qǐng)求路由
前面說過,Socket.D 是一個(gè)二進(jìn)制協(xié)議,但仍然可以在消息體中通過 metaString 來(lái)暴露信息給網(wǎng)絡(luò)中間件。每個(gè)消息實(shí)體的 metaString 會(huì)帶有‘@’參數(shù), 告訴 Socket.D Broker 消息應(yīng)該轉(zhuǎn)發(fā)給誰(shuí),從而實(shí)現(xiàn)路由效果。示例:
client.send("/demo", new StringEntity("").at("demoapp"));
與連接時(shí)給自己取名的 '@' 參數(shù)相乎應(yīng)。取了名,就能被“別人” at 到!
4.暴露服務(wù)不需要Ip和Port
整個(gè)架構(gòu)當(dāng)中,所有節(jié)點(diǎn)都只需要知道Broker的地址和服務(wù)端口即可。只要成功連接信息流就是雙向的。Borker可以直接通過建立的Connection尋址服務(wù)節(jié)點(diǎn),所有的服務(wù)調(diào)用者都不需要知道服務(wù)暴露方的地址
而Broker又可以通過連接的 url 地址,進(jìn)行簽權(quán)控制。
5.天生的中心化管理
管理微服務(wù)集群往往需要有一個(gè)中心化的控制中心,在這個(gè)架構(gòu)中 Socket.D Broker 就是自然而然的中心,知道整個(gè)集群中所有的情況。
總結(jié)
以上是生活随笔為你收集整理的Socket.D 基于消息的响应式应用层网络协议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学校智慧餐厅宣传标语文案30句
- 下一篇: Kernel Memory 入门系列:快