RPC, or Remote Procedure Call, is just to put it simply: calling services on remote computers is just like calling local services.
My project adopts a microservice architecture based on Restful. As communication between microservices becomes more and more frequent, the system resources are consumed more and more. So I hope it can be changed to using rpc for internal communication, and still use Restful for external purposes. So I thought of the rpc package of golang standard library and the grpc of google.
This article focuses on learning about golang's rpc package.
introduce
Golang's rpc supports three levels of RPC: TCP, HTTP, and JSONRPC. But Go's RPC package is a unique RPC. Unlike traditional RPC systems, it only supports the interaction between the server and the client developed by Go, because internally, they use Gob to encode.
Go RPC functions can only be accessed remotely if they meet the following conditions, otherwise they will be ignored. The detailed requirements are as follows:
- Functions must be exported (first letter capitalization)
- There must be two export type parameters,
- The first parameter is the received parameter, the second parameter is the parameter returned to the client-client, and the second parameter must be of pointer type
- The function must have a return value error
For example, the correct RPC function format is as follows:
func (t *T) MethodName(argType T1, replyType *T2) error
T, T1 and T2 types must be coded by encoding/gob packages.
Example
Let's give an example of http.
Here is the code on the http server:
package main import ( "errors" "net" "net/rpc" "log" "net/http" ) type Args struct { A, B int } type Quotient struct { Quo, Rem int } type Arith int func (t *Arith) Multiply(args *Args, reply *int) error { *reply = * return nil } func (t *Arith) Divide(args *Args, quo *Quotient) error { if == 0 { return ("divide by zero") } = / = % return nil } func main() { arith := new(Arith) (arith) () l, e := ("tcp", ":1234") if e != nil { ("listen error:", e) } (l, nil) }
Let’s briefly analyze the above example. First instantiate an Arith object arith, then register the rpc service for arith, and then mount the rpc service on the http service. When the http service is opened, we can use the rpc client to call the method that meets the rpc standards in the arith.
Please see the client's code:
package main import ( "net/rpc" "log" "fmt" ) type Args struct { A, B int } type Quotient struct { Quo, Rem int } func main() { client, err := ("tcp", "127.0.0.1:1234") if err != nil { ("dialing:", err) } // Synchronous call args := &Args{7,8} var reply int err = ("", args, &reply) if err != nil { ("arith error:", err) } ("Arith: %d*%d=%d\n", , , reply) // Asynchronous call quotient := new(Quotient) divCall := ("", args, quotient, nil) replyCall := <- // will be equal to divCall if != nil { ("arith error:", ) } ("Arith: %d/%d=%d...%d", , , , ) // check errors, print, etc. }
To give a brief explanation, first use the DialHTTP method of rpc to connect to the server side. To call the server side functions, you have to use the Call method. The parameters and return values of the Call method have clearly expressed the overall calling logic of rpc.
We run the server and then the client, and the client will output:
Arith: 7*8=56 Arith: 7/8=0...7
At this point, the entire rpc calling logic is completed.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.