XML-RPC JSON-RPC RPC是實現思路


 

XML-RPC - Wikipedia https://en.wikipedia.org/wiki/XML-RPC

JSON-RPC - Wikipedia https://en.wikipedia.org/wiki/JSON-RPC

 

An example of a typical XML-RPC request would be:

<?xml version="1.0"?>
<methodCall> <methodName>examples.getStateName</methodName> <params> <param> <value><i4>40</i4></value> </param> </params> </methodCall> 

An example of a typical XML-RPC response would be:

<?xml version="1.0"?>
<methodResponse> <params> <param> <value><string>South Dakota</string></value> </param> </params> </methodResponse> 

A typical XML-RPC fault would be:

<?xml version="1.0"?>
<methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>4</int></value> </member> <member> <name>faultString</name> <value><string>Too many parameters.</string></value> </member> </struct> </value> </fault> </methodResponse>

 

kj'lk

 

Examples[edit]

In these examples, --> denotes data sent to a service (request), while <-- denotes data coming from a service. Although <-- is often called a response in client–server computing, depending on the JSON-RPC version it does not necessarily imply an answer to a request.

Version 2.0[edit]

Request and response:

--> {"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 42, "subtrahend": 23}, "id": 3} <-- {"jsonrpc": "2.0", "result": 19, "id": 3} 

Notification (no response):

--> {"jsonrpc": "2.0", "method": "update", "params": [1,2,3,4,5]} 

Version 1.1 (Working Draft)[edit]

Request and response:

--> {"version": "1.1", "method": "confirmFruitPurchase", "params": [["apple", "orange", "mangoes"], 1.123], "id": "194521489"} <-- {"version": "1.1", "result": "done", "error": null, "id": "194521489"} 

Version 1.0[edit]

Request and response:

--> {"method": "echo", "params": ["Hello JSON-RPC"], "id": 1} <-- {"result": "Hello JSON-RPC", "error": null, "id": 1}

 

 

 

jkl

This is a basic request to view the jCard details for a single user (based on their username). This message would be passed in a request within the "json" parameter e.g.

?json={"HEAD":{"service_type":"contacts","action_type":"view", "sid":"80e5b8a8b9cbf3a79fe8d624628a0fe5"},"BODY":{"username":"jbloggs"}} 
{
    "HEAD" : { "service_type" : "contacts", "action_type" : "view", "sid" : "80e5b8a8b9cbf3a79fe8d624628a0fe5" }, "BODY" : { "username" : "jbloggs" } } 

This is a simple SOAPjr response with a HEAD.result that represents a success. The BODY contains a single jCard record. In a list "list" or "search" context this would contain an array of 0 or more jCard records.

{
    "HEAD" : { "result" : "1" }, "BODY" : { "email" : [ { "type" : ["internet","pref"], "value" : "spam@SOAPjr.org" } ], "fn" : "Joe Bloggs", "kind" : "individual", "n" : { "family-name" : ["Bloggs"], "given-name" : ["Joe"], "value" : "Bloggs;Joe" }, "org" : [ { "organization-name" : "SOAPjr.org" } ] } }

 

 

Remote procedure call - Wikipedia https://en.wikipedia.org/wiki/Remote_procedure_call

In distributed computing, a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in a different address space (commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction. That is, the programmer writes essentially the same code whether the subroutine is local to the executing program, or remote.[1] This is a form of client–server interaction (caller is client, executor is server), typically implemented via a request–response message-passing system. In the object-oriented programming paradigm, RPC calls are represented by remote method invocation (RMI). The RPC model implies a level of location transparency, namely that calling procedures is largely the same whether it is local or remote, but usually they are not identical, so local calls can be distinguished from remote calls. Remote calls are usually orders of magnitude slower and less reliable than local calls, so distinguishing them is important.

 

 

simple is better - JSON-RPC https://www.simple-is-better.org/rpc/

 

誰能用通俗的語言解釋一下什么是 RPC 框架? - 知乎 https://www.zhihu.com/question/25536695

  • 首先,要解決通訊的問題,主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調用的所有交換的數據都在這個連接里傳輸。連接可以是按需連接,調用結束后就斷掉,也可以是長連接,多個遠程過程調用共享同一個連接。
  • 第二,要解決尋址的問題,也就是說,A服務器上的應用怎么告訴底層的RPC框架,如何連接到B服務器(如主機或IP地址)以及特定的端口,方法的名稱名稱是什么,這樣才能完成調用。比如基於Web服務協議棧的RPC,就要提供一個endpoint URI,或者是從UDDI服務上查找。如果是RMI調用的話,還需要一個RMI Registry來注冊服務的地址。
  • 第三,當A服務器上的應用發起遠程過程調用時,方法的參數需要通過底層的網絡協議如TCP傳遞到B服務器,由於網絡協議是基於二進制的,內存中的參數的值要序列化成二進制的形式,也就是序列化(Serialize)或編組(marshal),通過尋址和傳輸將序列化的二進制發送給B服務器。
  • 第四,B服務器收到請求后,需要對參數進行反序列化(序列化的逆操作),恢復為內存中的表達方式,然后找到對應的方法(尋址的一部分)進行本地調用,然后得到返回值。
  • 第五,返回值還要發送回服務器A上的應用,也要經過序列化的方式發送,服務器A接到后,再反序列化,恢復為內存中的表達方式,交給A服務器上的應用

Remote Procedure Calls https://www.cs.rutgers.edu/~pxk/417/notes/03-rpc.html

 

Implementing remote procedure calls

Several issues arise when we think about implementing remote procedure calls.

How do you pass parameters?

Passing by value is simple: just copy the value into the network message. Passing by reference is hard. It makes no sense to pass an address to a remote machine since that memory location likely points to something completely different on the remote system. If you want to support passing by reference, you will have to send a copy of the arguments over, place them in memory on the remote system, pass a pointer to them to the server function, and then send the object back to the client, copying it over the reference. If remote procedure calls have to support references to complex structures, such as trees and linked lists, they will have to copy the structure into a pointerless representation (e.g., a flattened tree), transmit it, and reconstruct the data structure on the remote side.

How do we represent data?

On a local system there are no data incompatibility problems; the data format is always the same. With RPC, a remote machine may have different byte ordering, different sizes of integers, and a different floating point representation.

For example, big endian representation stores the most significant bytes of a multi-byte integer in low memory. Little endian representation stores the most significant bytes of an integer in high memory. Many older processors, such as Sun SPARCs and the Motorola 680x0s used big endian storage. Most Intel systems implemented little endian storage, which led to the dominance of this format. Many other architectures use a bi-endian format, where the processor can be configured at boot time to operate in either little endian or big endian mode. Examples of these processors are ARM, MIPS, PowerPC, SPARC v9, and Intel IA–64 (Itanium).

The problem was dealt with in the IP protocol suite by forcing everyone to use big endian byte ordering for all 16 and 32 bit fields in headers (hence the use of htons and htonlfunctions). For RPC, we need to come up with a “standard” encoding for all data types that can be passed as parameters if we are to communicate with heterogeneous systems. ONC RPC, for example, uses a format called XDR (eXternal Data Representation) for this process. These data representation formats can use implicit or explicit typing. With implicit typing, only the value is transmitted, not the name or type of the variable. ONC RPC’s XDR and DCE RPC’s NDR are examples of data representations that use implicit typing. With explicit typing, the type of each field is transmitted along with the value. The ISO standard ASN.1 (Abstract Syntax Notation), JSON (JavaScript Object Notation), Google Protocol Buffers, and various XML-based data representation formats use explicit typing.

What machine and port should we bind to?

We need to locate a remote host and the proper process (port or transport address) on that host. One solution is to maintain a centralized database that can locate a host that provides a type of service. This is the approach that was proposed by Birell and Nelson in their 1984 paper introducing RPC. A server sends a message to a central authority stating its willingness to accept certain remote procedure calls. Clients then contact this central authority when they need to locate a service. Another solution, less elegant but easier to administer, is to require the client to know which host it needs to contact. A name server on that host maintains a database of locally provided services.

What transport protocol should be used?

Some implementations allow only one to be used (e.g. TCP). Most RPC implementations support several and allow the user to choose.

What happens when things go wrong?

There are more opportunities for errors now. A server can generate an error, there might be problems in the network, the server can crash, or the client can disappear while the server is running code for it. The transparency of remote procedure calls breaks here since local procedure calls have no concept of the failure of the procedure call. Because of this, programs using remote procedure calls have to be prepared to either test for the failure of a remote procedure call or catch an exception.

What are the semantics of remote calls?

The semantics of calling a regular procedure are simple: a procedure is executed exactly once when we call it. With a remote procedure, the exactly once aspect is quite difficult to achieve. A remote procedure may be executed:

  • 0 times if the server crashed or process died before running the server code.
  • once if everything works fine.
  • once or more if the server crashed after returning to the server stub but before sending the response. The client won’t get the return response and may decide to try again, thus executing the function more than once. If it doesn’t try again, the function is executed once.
  • more than once if the client times out and retransmits. It is possible that the original request may have been delayed. Both may get executed (or not).

RPC systems will generally offer either at least once or at most once semantics or a choice between them. One needs to understand the nature of the application and function of the remote procedures to determine whether it is safe to possibly call a function more than once. If a function may be run any number of times without harm, it is idempotent(e.g., time of day, math functions, read static data).  Otherwise, it is a nonidempotent function (e.g., append or modify a file).

What about performance?

A regular procedure call is fast: typically only a few instruction cycles. What about a remote procedure call? Think of the extra steps involved. Just calling the client stub function and getting a return from it incurs the overhead of a procedure call. On top of that, we need to execute the code to marshal parameters, call the network routines in the OS (incurring a mode switch and a context switch), deal with network latency, have the server receive the message and switch to the server process, unmarshal parameters, call the server function, and do it all over again on the return trip. Without a doubt, a remote procedure call will be much slower. We can easily expect the overhead of making the remove call to be thousands of times slower than a local one. However, that should not deter us from using remote procedure calls since there are usually strong reasons for moving functions to the server.

What about security?

This is definitely something we need to worry about. With local procedures, all function calls are within the confines of one process and we expect the operating system to apply adequate memory protection through per-process memory maps so that other processes are not privy to manipulating or examining function calls. With RPC, we have to be concerned about various security issues:

  • Is the client sending messages to the correct remote process or is the process an impostor?

  • Is the client sending messages to the correct remote machine or is the remote machine an impostor?

  • Is the server accepting messages only from legitimate clients? Can the server identify the user at the client side?

  • Can the message be sniffed by other processes while it traverses the network?

  • Can the message be intercepted and modified by other processes while it traverses the network from client to server or server to client?

  • Is the protocol subject to replay attacks? That is, can a malicious host capture a message an retransmit it at a later time?

  • Has the message been accidentally corrupted or truncated while on the network?

 

作者:洪春濤
鏈接:https://www.zhihu.com/question/25536695/answer/221638079
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

本地過程調用

RPC就是要像調用本地的函數一樣去調遠程函數。在研究RPC前,我們先看看本地調用是怎么調的。假設我們要調用函數Multiply來計算lvalue * rvalue的結果:

1 int Multiply(int l, int r) { 2 int y = l * r; 3 return y; 4 } 5 6 int lvalue = 10; 7 int rvalue = 20; 8 int l_times_r = Multiply(lvalue, rvalue); 

那么在第8行時,我們實際上執行了以下操作:

  1. 將 lvalue 和 rvalue 的值壓棧
  2. 進入Multiply函數,取出棧中的值10 和 20,將其賦予 l 和 r
  3. 執行第2行代碼,計算 l * r ,並將結果存在 y
  4. 將 y 的值壓棧,然后從Multiply返回
  5. 第8行,從棧中取出返回值 200 ,並賦值給 l_times_r

以上5步就是執行本地調用的過程。(20190116注:以上步驟只是為了說明原理。事實上編譯器經常會做優化,對於參數和返回值少的情況會直接將其存放在寄存器,而不需要壓棧彈棧的過程,甚至都不需要調用call,而直接做inline操作。僅就原理來說,這5步是沒有問題的。)

 

遠程過程調用帶來的新問題

在遠程調用時,我們需要執行的函數體是在遠程的機器上的,也就是說,Multiply是在另一個進程中執行的。這就帶來了幾個新問題:

  1. Call ID映射。我們怎么告訴遠程機器我們要調用Multiply,而不是Add或者FooBar呢?在本地調用中,函數體是直接通過函數指針來指定的,我們調用Multiply,編譯器就自動幫我們調用它相應的函數指針。但是在遠程調用中,函數指針是不行的,因為兩個進程的地址空間是完全不一樣的。所以,在RPC中,所有的函數都必須有自己的一個ID。這個ID在所有進程中都是唯一確定的。客戶端在做遠程過程調用時,必須附上這個ID。然后我們還需要在客戶端和服務端分別維護一個 {函數 <--> Call ID} 的對應表。兩者的表不一定需要完全相同,但相同的函數對應的Call ID必須相同。當客戶端需要進行遠程調用時,它就查一下這個表,找出相應的Call ID,然后把它傳給服務端,服務端也通過查表,來確定客戶端需要調用的函數,然后執行相應函數的代碼。
  2. 序列化和反序列化。客戶端怎么把參數值傳給遠程的函數呢?在本地調用中,我們只需要把參數壓到棧里,然后讓函數自己去棧里讀就行。但是在遠程過程調用時,客戶端跟服務端是不同的進程,不能通過內存來傳遞參數。甚至有時候客戶端和服務端使用的都不是同一種語言(比如服務端用C++,客戶端用Java或者Python)。這時候就需要客戶端把參數先轉成一個字節流,傳給服務端后,再把字節流轉成自己能讀取的格式。這個過程叫序列化和反序列化。同理,從服務端返回的值也需要序列化反序列化的過程。
  3. 網絡傳輸。遠程調用往往用在網絡上,客戶端和服務端是通過網絡連接的。所有的數據都需要通過網絡傳輸,因此就需要有一個網絡傳輸層。網絡傳輸層需要把Call ID和序列化后的參數字節流傳給服務端,然后再把序列化后的調用結果傳回客戶端。只要能完成這兩者的,都可以作為傳輸層使用。因此,它所使用的協議其實是不限的,能完成傳輸就行。盡管大部分RPC框架都使用TCP協議,但其實UDP也可以,而gRPC干脆就用了HTTP2。Java的Netty也屬於這層的東西。

所以,要實現一個RPC框架,其實只需要把以上三點實現了就基本完成了。

Call ID映射可以直接使用函數字符串,也可以使用整數ID。映射表一般就是一個哈希表。

序列化反序列化可以自己寫,也可以使用Protobuf或者FlatBuffers之類的。

網絡傳輸庫可以自己寫socket,或者用asio,ZeroMQ,Netty之類。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM