起因:
研究zabbix的API設計風格。查看zabbix官網API文檔,可以看到使用的是json-rpc:2.0
隨後搜索到知乎上的一個問題討論:https://www.zhihu.com/question/28570307 即標題中的問題。
仔細研究,問題不斷髮散再發散,整理一下,以下內容是看了很多篇相關知識後的個人理解:
1、RPC是什麼?
參考:https://www.zhihu.com/question/25536695/answer/221638079
RPC是指遠程過程調用。服務器A要調用服務器B上的某個方法,由於內存空間不同,無法直接調用,需要通過網絡來表達調用的語義和傳達調用的數據。需解決以下問題:
通信問題:在服務器A與B之間建立起TCP連接(有答案說UDP也可以);TCP、UDP是屬於傳輸層的協議
參數的序列化和反序列化:參數通過網絡傳輸,需把服務器A內存裏的內容序列化後進行傳輸。
方法映射:參數中包含着要調用的方法,服務器B必須建立起參數與所要調用方法的映射關係
服務器B執行完方法後返回,同樣經歷上述過程。
2、json-RPC是什麼
json-rpc 2.0規範:http://wiki.geekdream.com/Specification/json-rpc_2.0.html
JSON-RPC是一個無狀態且輕量級的遠程過程調用(RPC)協議。 本規範主要定義了一些數據結構及其相關的處理規則。它允許運行在基於socket,http等諸多不同消息傳輸環境的同一進程中。
簡單來說,就是定義了各個RPC各參數規範。如method表示方法,param表示參數。服務器B拿到這個東西就是知道了服務器A要調用什麼方法,參數是什麼。
它是運行在socket、http、websocket等協議之上的。注意http、websocket已經是屬於應用層了。
3、什麼是websocket?它和socket有什麼區別?
介紹websocket: https://blog.csdn.net/wwd0501/article/details/54582912
websocket首先是一個應用層協議,這點與http相同。
與http不同的是,它可以建立服務器A與服務器B之間的一個長連接(類似於TCP中的長連接),之後可以發送多個請求。而http每一個請求都是獨立的。據介紹,websocket建立長連接時,使用http,之後的請求與返回,則不需要http協議了。
socket是傳輸層與應用層之間的一個抽象層,爲應用層屏蔽了傳輸層複雜的協議。
4、什麼是RESTful?
restful是一種API設計風格。這裏可以發現,其實restful和json-rpc其實是沒有可比性的。其對比的應該是RPC.
restful必須依賴於http,因爲它需要http請求的類型(post、get、put、delete)來標榜對該資源進行如何的處理。
restful設計難點:需要將所有的接口抽象成某種資源
如想delete多個id怎麼辦?全部寫在url中嗎(delete沒有body)?不,你應該把刪除多個ID抽象成某個任務(即抽象成另一種資源),然後對這個資源使用post。比如用戶的登錄和登出,不適合對用戶這個資源進行操作,應該抽象成對session這個資源進行操作。
想使用restful必須要有這樣的抽象能力。。
知乎對restful一個總結(個人覺得挺到位的):
看Url就知道要什麼(資源)
看http method就知道幹什麼
看http status code就知道結果如何
一定要有以資源爲主體的思維。之前也有人說過restful是名詞,rpc是動詞,大概想表述的也是這個意思。
5、知乎中有人說json-rpc性能比restful好?
其實是json-rpc能運行在類似於websocket上,是websocket的性能比http好。這種說法有點問題。
像zabbix,json-rpc底層承載還是使用http,反而需要序列化和反序列化的時間,性能好?不見得吧。
6、說回zabbix,其API設計風格到底是咋樣的?
首先,開放的API都是使用http的post方法調用的,post的參數遵循json-rpc2.0的規範。如果把所有的API接口看成一種資源,那它的這個API可以說是遵循了restful風格。
其次,最新奇的一點來了,其API的URL只有一個!!只有一個!!格式如下:
POST http://company.com/zabbix/api_jsonrpc.php HTTP/1.1 Content-Type: application/json-rpc {"jsonrpc":"2.0","method":"apiinfo.version","id":1,"auth":null,"params":{}}
去看了api_jsonrpc.php,這個php腳本要解決的就是,首先拿到http的body數據,接下來用json-rpc2.0規範去解析,拿到method到底是什麼,接下來去調用相應的方法。這個腳本做的就是RPC中提到的要解決方法映射問題。
有意思的是,method全都是以這樣的形式A.B,給人一種感覺,A是類,B是A中某個方法。zabbix中所有的方法都用php腳本實現了,對應的每一個A都是獨立的一個php文件,B是A中的某個方法,且名稱是一一對應的,即無需維護參數中的名稱與調用方法的映射關係。
假設不使用zabbix的Php腳本來實現類似的功能,使用類的getMethod的方式,通過反射來調用個人覺得也是可行,當然方法名稱自然也是要一一對應的。
暫時不能理解,爲什麼zabbix要這樣設計(僅用一個URL,在json-rpc的method字段去標註具體的方法)?或者這樣設計的好處在哪裏?知乎上有人這樣說:
我見過最高明的restful設計,是隻使用一個url,然後,用post請求,傳method動詞參數。可謂一個restful在手,打遍天下無敵手。
這難不成說的就是zabbix????
最後,引用知乎上的一段話:
所謂代碼風格、接口形式、各種林林總總的格式規定,其實都是爲了在團隊內部形成共識、防止個人習慣差異引起的混亂。JSON-RPC當然也是有規範的,但相比REST實在寬鬆太多了。
如果一個開發團隊規定必須在url裏寫action,所有請求都是POST,可以嗎?當然也沒問題,只是不要拿出去標榜自己寫的是RESTful API就行。
規範最終還是爲了開發者和軟件產品服務的,如果它能帶來便利、減少混亂,就值得用;反之,如果帶來的麻煩比解決的還多,那就犯不上純粹跟風追流行了。(作者:Vincross 鏈接:https://www.zhihu.com/question/28570307/answer/163638731)