1. 程式人生 > >json-rpc 1.0規範解讀

json-rpc 1.0規範解讀

JSON可能是這個地球上最簡單的文字資料格式了,可讀、靈活、資料量小,編解碼方便、速度快,對Unicode和特殊字元支援的好。對比下XML,就知道額外的各種標籤節點需要浪費多少位元組數。JSON字元預設都要使用Unicode形式,所有非ACSII字元都可以用\uXXXX表示,而不需要額外的轉義。相比之下,XML裡需要使用轉義或是CDATA(類似HTML裡的PRE標籤)、或是Base64才能表示特殊資料。當然缺點也很明顯,比二進位制資料結構的資料量大,編解碼慢,沒有完備的型別系統,表達能力有限。

JSON-RPC是一個使用json物件作為資料載體的遠端過程呼叫(Remote Process Call,RPC)技術。

"Does distributed computing have to be any harder than this? I don't think so." -- Jan-Klaas Kollhof

JSON-RPC的設計目標就是兩個字:簡單。我們知道一個rpc框架是為了2個系統間的互動通訊,這就需要定義一箇中間的資料傳輸格式。為了跟系統本身用的平臺數據結構轉換,需要提供一套序列化和反序列化這個資料格式的功能。然後就是需要某種通訊協議來傳輸實際遠端呼叫的資料。最後還需要通訊的兩端有實現的程式碼樁(stub&skeleton),這一般是基於動態代理或AOP實現的代理,一個可供呼叫的介面結構,使得框架隱藏了其他所有的技術細節(資料格式、序列化、網路傳輸等),程式裡能像本地方法呼叫一樣呼叫遠端的方法。總結一下:

  1. 資料格式
  2. 序列化功能
  3. 通訊協議
  4. 程式碼樁

JSON-RPC規範裡只顯式規定了資料格式(即JSON),建議了通訊協議(TCP或是HTTP),序列化和程式碼樁沒有提及。當然序列化比較好辦,各種語言裡都有豐富的JSON序列化庫(參見參考資料1)。那麼程式碼樁就完全留給了實現JSON-RPC規範的框架自己去處理了,通訊協議這一塊的具體處理也大部分需要框架自己考慮。

我們知道兩個系統的通訊,可能是同步阻塞的(每個請求要等響應完成以後再發下一個請求),也可能是非同步非阻塞的(請求1發完,繼續發請求2,哪個響應回來就處理哪個響應);也可能是單向的(one-way,發了就不管了、不要響應資訊),也可能是請求-響應的(request-response),每個請求都需要有顯式的回覆。

JSON-RPC1.0裡,把通訊的雙方當做對等的兩個端。

  • 定義瞭如何發請求和返回結果、出錯資訊,
  • 如何處理單向和請求-響應的互動過程,
  • 以及雙向非同步請求如何匹配結果和請求,
  • 最後還添加了一個簡單的型別提示(class hinting)擴充套件功能(想法很好,但是就兩句話沒細節,挺雞肋的)。

我們來具體看看規範的內容。

請求(request)

請求端傳送一個JSON物件表示自己要呼叫的方法,示例如下:

{ "method": "echo", "params": ["Hello JSON-RPC"], "id": 1}

其中包含三個關鍵元素:

  • method:表示要呼叫的方法
  • params:表示引數的陣列
  • id:表示這次請求是需要響應的,服務方需要提供一個同樣是id為1的響應資訊。

這個id欄位非常有意思,一般的同步RPC都不需要考慮這個東西,因為一般情況下,一個RPC請求只包含一個請求,並且請求會等待響應資訊返回,在這之前一直會阻塞呼叫方的處理執行緒,這樣整個RPC才像是呼叫的本地方法。

響應(response)

一個典型的響應資訊如下:

{ "result": "Hello JSON-RPC", "error": null, "id": 1}

關鍵元素也是3個:

  • result:表示返回結果,如果出錯result必須為null
  • error:表示出錯,如果請求成功,則error必須為null
  • id:表示為此響應對應的請求id

通知(notification)

通知資訊類似一個請求,但是id必須為null。通知代表單向的請求,不能回覆,可以由請求方傳送給服務方,也可以由服務方傳送給請求方(協議原則上要求雙方對等,都可以是請求方或服務方,這一點上HTTP其實是不滿足的)。

通訊(transport)

  • TCP

協議推薦通訊雙方在TCP下使用位元組流(byte stream)的方式互動。此時雙方是對等的。關閉連線前必須給所有未應答的請求方傳送一個錯誤資訊。無效的請求或響應將會導致連線關閉。

  • HTTP

在一些限制的條件下,也可以使用HTTP作為通訊協議。此時通訊雙方明顯不在對等,有了客戶端和伺服器端。

考慮到HTTP的開銷問題,協議允許一次POST可以帶上多個rpc請求或通知。由於HTTP下,server不能夠主動訪問client,所以server可以在HTTP響應中附帶上自己的請求和通知。這個地方協議們沒有說清楚具體操作,細節也是個蛋疼的事兒。

型別提示(class hinting)

非常簡單,就是加了個屬性表示建構函式constructor,可以用引數[param1,...]來初始化物件。而且如果物件初始化的時候呼叫了這個構造器,那麼相應的屬性(比如prop1)也會新增到物件,示例程式碼:

{"__jsonclass__":["constructor", [param1,...]], "prop1": ...}

協議沒有具體說清楚這個地方,具體怎麼操作,怎麼對應原生環境裡的型別,蛋疼++。

一個多次通訊的例子

JSON-RPC過程如下,其中-->代表傳送資料到服務方,<--代表服務方的響應:

--> {"method": "postMessage", "params": ["Hello all!"], "id": 99}
<-- {"result": 1, "error": null, "id": 99}
<-- {"method": "handleMessage", "params": ["user1", "we were just talking"], "id": null}
<-- {"method": "handleMessage", "params": ["user3", "sorry, gotta go now, ttyl"], "id": null}
--> {"method": "postMessage", "params": ["I have a question:"], "id": 101}
<-- {"method": "userLeft", "params": ["user3"], "id": null}
<-- {"result": 1, "error": null, "id": 101}

關於JSON-RPC1.0規範的進一步討論

  • 關於通知

通知機制也可以用於類似FTP協議的NOOP,或是其他通訊協議裡的Keep Alive心跳機制。在具體使用的過程中,定時的傳送通知來確認雙方都線上,並且可以捎帶非同步處理的資訊。

  • 關於id

請求中id欄位的作用,就跟JMS協議裡的correlationID一樣,可以起到區分多個請求的作用,這樣又兩個好處:

  1. 多個請求可以打包成一個請求,返回也可以返回多個響應,處理方按照id區分多個數據即可;
  2. 可以做非同步的響應,反正我不保證順序了,也能根據id來匹配原來是哪個請求來著。

特別是配合HTTP和通知功能,使得非同步呼叫變得可能:客戶端直接傳送請求1後返回,繼續傳送請求2,請求3...等等;服務端在處理完成請求1後,可能把響應放到請求2或3的HTTP response報文返回,或者在接下里的某次互動裡返回即可。

  • 關於型別

JSON-RPC跟XML-RPC非常型別,但是藉助於XML本身的schema結構,XML-RPC定義了一套基礎的資料型別、以及在基礎上的構造複雜資料型別的能力,這樣XML-RPC中就可以用於更復雜的業務互動場景。而JSON-RPC使用JS原生的弱型別,只能表示非常簡單和模糊的元資料結構,不利於複雜場景和實現程式碼樁的生成工具。如果有一些更有效的schema約束,則可以把JSON-RPC應用得更廣泛。

參考資料

相關推薦

json-rpc 1.0規範解讀

JSON可能是這個地球上最簡單的文字資料格式了,可讀、靈活、資料量小,編解碼方便、速度快,對Unicode和特殊字元支援的好。對比下XML,就知道額外的各種標籤節點需要浪費多少位元組數。JSON字元預設都要使用Unicode形式,所有非ACSII字元都可以用\uXXXX表

Oracle 12.1.0.2 對JSON的支持

使用 lin 1.5 text lob mysq 索引 acl var Oracle 12.1.0.2版本有一個新功能就是可以存儲、查詢、索引JSON數據格式,而且也實現了使用SQL語句來解析JSON,非常方便。JSON數據在數據庫中以VARCHAR2, CLOB或者BLO

分布式消息規範 OpenMessaging 1.0.0-preview 發布

RoCE 異常 ons ade 事務 review con manage preview 摘要: OpenMessaging 是由阿裏巴巴牽頭發起,由 Yahoo、滴滴、Streamlio、微眾銀行、Datapipeline 等公司共同發起創建的分布式消息規範,其目標在於打

Oracle 12.1.0.2 對JSON的支援

Oracle 12.1.0.2版本有一個新功能就是可以儲存、查詢、索引JSON資料格式,而且也實現了使用SQL語句來解析JSON,非常方便。JSON資料在資料庫中以VARCHAR2, CLOB或者BLOB進行儲存。Oracle建議使用者在插入JSON資料之前,使用is_json來驗證輸入JSO

從零寫分散式RPC框架 系列 1.0 (2)RPC-Common模組設計實現

RPC-Common模組提供RPC-Server和RPC-Client的通用物件,封裝統一規則,使RPC Server和RPC Client 可以基於同一協議通訊。主要包含底層通訊的Netty所需的編碼解碼器(RpcEncoder,RpcDecoder),實現自定義協議的傳輸物件(Rpc

從零寫分散式RPC框架 系列 1.0 (5)整合測試

本篇將對前面幾篇模組作整合處理,使用spring-boot-starter的形式進行釋出。然後新建 examples 工程模組對其測試使用。 系列文章: 從零寫分散式RPC框架 系列 1.0 (1)架構設計 從零寫分散式RPC框架 系列 1.0 (2)RPC-Common模組設計

從零寫分散式RPC框架 系列 1.0 (4)RPC-Client模組設計實現

RPC-Client模組負責建立 動態代理物件 供 服務消費者 使用,而動態代理物件的方法執行則是通過RPC呼叫RPC-Server的服務實現。即RPC-Client遮蔽了底層的通訊過程,使得服務消費者可以基於介面透明使用服務提供者的服務。 系列文章: 從零寫分散式RPC框架 系

從零寫分散式RPC框架 系列 1.0 (3)RPC-Server模組設計實現

RPC-Server模組負責(1)將@RpcService註解標記的服務和自身資訊註冊到ZK叢集,(2)對外提供RPC服務實現,處理來自RPC-Client的請求。該模組整體的核心類為 RpcServer ,而真正處理請求的核心類是 RpcServerHandler 。另外還有一個 ZK

Aittit rpc的實現協議 JSON-RPC XML-RPC . Ws協議webservice 目錄 1. XML-RPC協議 1 1.1. JSON-RPC遠端呼叫協議 - CieloSun

Aittit rpc的實現協議  JSON-RPC XML-RPC . Ws協議webservice   目錄 1. XML-RPC協議 1 1.1. JSON-RPC遠端呼叫協議 - CieloSun - 部落格園.html 1 1.2.

分散式訊息規範 OpenMessaging 1.0.0-preview 釋出

OpenMessaging 是由阿里巴巴牽頭髮起,由 Yahoo、滴滴、Streamlio、微眾銀行、Datapipeline 等公司共同發起建立的分散式訊息規範,其目標在於打造廠商中立,面向 Cloud Native ,同時對流計算以及大資料生態友好的下一代分散式

Spark2.1.0——內建RPC框架詳解

private TransportClient createClient(InetSocketAddress address) throws IOException, InterruptedException { logger.debug("Creating new connecti

RapidJson(V1.1.0)的Value簡單操作(拼接json串,存取檔案中的json,解析json串)

#include <rapidjson/document.h> #include <rapidjson/stringbuffer.h> #include <rapidjson/pointer.h> #include <rapidjson/writer.h

Aittit rpc的實現協議 JSON-RPC XML-RPC . Ws協議webservice 目錄 1. XML-RPC協議 1 1.1. JSON-RPC遠端呼叫協議

Aittit rpc的實現協議  JSON-RPC XML-RPC . Ws協議webservice 目錄 XML-RPC協議 xml-rpc 是一套規範及其一系列的實現,允許執行在不同作業系統、不同環境的程式基於internet進行

iOS網路框架AFNetworking3.1.0底層原始碼解讀

AFNetworking基本是iOS開發中的網路第三方庫標配,本文基於AFNetworking3.1.0版本。咱們主要從使用的角度來介紹AFNetworking的發起Get請求的過程,偏重於解讀過程,解讀當你使用AFNetworking發起一個Get請求的時候,

springboot整合springdataJPA 2.1.0 返回json資料異常

提示資訊如下 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddy

mybatis測試類的連結規範1.0

public static void main(String[] args) throws Exception { //獲取xml檔案的路徑 String resource = "config/SqlMapConfig.xml"; //配置路徑

LoRaWAN 規範 1.0 (章節5)

最近在做LoRa, LoRaWAN協議略微複雜,邊讀邊翻譯,現在把部分關鍵的翻譯分享給各位做物聯網的同行。 當然裡面摻雜了一些我的個人筆記,希望對大家有所幫助。 如果哪裡有問題,歡迎應各位留言或者郵件指正。 翻譯很辛苦,轉載請註明

Spark2.1.0之內建RPC框架

        在Spark中很多地方都涉及網路通訊,比如Spark各個元件間的訊息互通、使用者檔案與Jar包的上傳、節點間的Shuffle過程、Block資料的複製與備份等。在Spark 0.x.x與Spark 1.x.x版本中,元件間的訊息通訊主要藉助於Akka[1],使

人臉特徵提取DeepID 1.0深度網路解讀

標籤: 深度學習 人臉校驗 DeepID 1.概述 文章名稱:Deep Learning Face Representation from Predicting 10,000 Classes 文章來源:2014CVPR 文章作者:Yi Sun,

微信跳一跳python自動程式碼解讀1.0

微信跳一跳 那個跳一跳python“外掛”,有幾個python檔案,其中有一個是得到截圖,然後滑鼠在圖片上點選兩次,python視窗上會列印兩次滑鼠的位置,並且會跟上一行這兩個點之間的距離。 這個功能我先給除去獲取截圖,就說怎麼在某張圖片上算出兩次點選的