RPC remote calling mechanism

The internal principle of RPC technology is realized by the combination of two technologies: local method invocation and network communication technology.

Introduction to RPC

  RPC is the acronym for Remote Procedure Call Protocol, abbreviated as: RPC, translated into Chinese called remote procedure call protocol. The so-called remote procedure call, the popular understanding is that you can call the function method of the program running on another server in the local program. This calling process transcends the limitations of the physical server and is done in the network. During the calling of the program on the remote server, the local program waits to return the calling result until the remote program is executed and returns the result to the local , And finally complete a complete call.

  It should be emphasized that the remote procedure call refers to the entire process of calling the program on the remote server .

RPC design composition

  RPC technology consists of four parts in architecture design, namely: client, client stub, server, server stub .

    Client : The initiator of the service call, also known as the service consumer.

    Client stub (Client Stub) : This program runs on the computer machine where the client is located, and is mainly used to store the address of the server to be called. In addition, the program is also responsible for packaging the data information of the client requesting the remote server program into The data packet is sent to the server Stub program through the network; secondly, it also needs to receive the call result data packet sent by the server Stub program, and parse it back to the client.

    Server : A program running on a remote computer machine, which has methods to be called by the client.

    Server stub (Server Stub) : Receive the request message data packet sent by the client Stub program through the network, and call the real program function method in the server to complete the function call; secondly, the server will perform the data processing package and send Stub program to the client.

RPC principle and calling steps

  

 

  In the above figure, the call process of each step of RPC is illustrated in the form of steps illustrated in steps 1-10. The specific description is:

    1. The client wants to initiate a remote procedure call by first calling the function method name to be used by calling the local client stub program;

    2. The client stub program receives the client's function call request, serializes the method name, parameter and other information carried by the client request and packages it into a data package .

    3. The client Stub finds the IP address of the remote server program, calls the Socket communication protocol, and sends it to the server through the network.

    4. The server Stub program receives the data packet information sent by the client, and deserializes the data through the agreed protocol to obtain the requested method name and request parameters .

    5. The server stub program prepares the relevant data, calls the corresponding function method of the local server, and passes in the corresponding parameters for business processing.

 

      6. The server program executes the calling process according to the existing business logic. After the business execution is completed, the execution result is returned to the server stub program.

    7. The server stub program serializes the program call result according to the agreed protocol and sends it back to the client stub program through the network.

    8. The client Stub program receives the returned data sent by the server Stub, deserializes the data, and passes the data returned by the call to the client request initiator.

    9. The client requests the initiator to get the call result, and the entire RPC call process ends.

Related technologies related to RPC

  1. Dynamic proxy technology : The client stub and sever stub programs we mentioned above are all programs that are automatically generated using dynamic proxy technology during the specific coding and development practice.

  2. Serialization and deserialization : During the RPC call, we can see that the data needs to be transferred from one machine to another. On the Internet, all data is transmitted in the form of bytes. In the process of programming, we often use data objects, so if we want to transfer data objects and related variables on the network, we need to serialize and deserialize the data objects.

    Serialization : The process of converting an object into a sequence of bytes is called serialization of the object, which is the process of encoding.

    Deserialization : The process of restoring a sequence of bytes to an object is called deserialization of the object, which is the process of decoding.

RPC official library

  In the pkg description of the Go language official website, the officially supported rpc package is provided, and the specific link is as follows: https://golang.org/pkg/net/rpc/ . The complete package name of the official rpc package is: net / rpc. According to the official explanation, the rpc package mainly provides the function of accessing an object through the network.

net / rpc library implements RPC call programming

1. Service definition and exposure

  In the process of programming, the server needs to register the structure object, and then expose it to the caller through the method to which the object belongs to provide services. This method is called the output method , and this output method can be called remotely. Of course, when defining the output method, the method that can be called remotely needs to follow certain rules. We explain through the code:

func (t *T) MethodName(request T1,response *T2) error

  The above code is the definition standard of the exposed service method given by the go language official, which contains several main rules, namely:

    1. The methods of external exposure can only have two parameters, and these two parameters can only be one of the output type or the built-in type.

    2. The second parameter of the method must be a pointer type.

    3. The return type of the method is error.

    4. The type of method is exportable.

    5. The method itself is also exportable.

  

type MathUtil struct {
}

func (this *MathUtil) CalculateCircleArea(req float32, resp *float32) error {
    *resp = math.Pi * req * req
    return nil
}

 

2. Registration service and monitoring request

// 1, initialize the pointer data type 
mathUtil: = new (MathUtil)

// 2, call the function of the net / rpc package to register the service object
err: = rpc.Register (mathUtil)
if err! = Nil {
panic (err. Error ())
}

// 3. Use this function to register the service provided in mathUtil to the HTTP protocol, so that the caller can use http to transfer data
rpc.HandleHTTP ()

// 4. Listen on a specific port
listen, err: = net.Listen ("tcp", ": 8081")
if err! = nil {
panic (err.Error ())
}
go http.Serve (listen, nil)

Third, the client calls

  The server is waiting for connection through the Http port monitoring method, so the client needs to connect through http, and first connect with the server.

  

client, err := rpc.DialHTTP("tcp", "localhost:8081")
    if err != nil {
        panic(err.Error())
    }

    var req float32
    req = 3

    var resp *float32
    err = client.Call("MathUtil.CalculateCircleArea", req, *resp)
    if err != nil {
        panic(err.Error())
    }
    fmt.Println(*resp)

  The core of the above call method lies in the call of the client.Call method. This method has three parameters. The first parameter indicates the method name of the remote service to be called. The second parameter is the parameter to be passed in when calling. The third The parameter is the return value to be received by the call.
  The above call method is implemented by synchronous call. In addition, there is an asynchronous way to call. Call the code asynchronously

    var respSync * float32
     // Asynchronous call 
    syncCall: = client.Go ( " MathUtil.CalculateCircleArea " , req, & respSync, nil) 
    replayDone: = < -syncCall.Done 
    fmt.Println (replayDone) 
    fmt.Println ( * respSync )    

Multi-parameter request call parameter passing

  Define the parameters in a new structure and store them in the param package:

type AddParma struct { 
    Args1 float32 // first parameter 
    Args2 float32 // second parameter 
}

  In the server.go file, implement the function of adding two numbers, and implement the logic of service registration:

func (mu * MathUtil) Add (param param.AddParma, resp * float32) error {
     * resp = param.Args1 + param.Args2 // Realize the function of adding two numbers
     return nil 
} 
mathUtil: = new (MathUtil) 

    err: = rpc.RegisterName ( " MathUtil " , mathUtil)
     if err! = nil { 
        panic (err.Error ()) 
    } 

    rpc.HandleHTTP () 

    listen, err: = net.Listen ( " tcp " , " : 8082 " ) 
    http .Serve (listen, nil)

 

Use RPC in combination with Protobuf

  Requirements: Suppose there is an order module (Order) in a system, and other modules want to implement remote engineering calls of RPC, and order information can be obtained according to the order ID and time stamp. If the acquisition is successful, the corresponding order information is returned; if the query fails to return the failure information. Now, let's program the requirements.

Transmission data format definition

  Data definition

  According to the requirements, define the message.proto file, which is defined as follows:

syntax = " proto3 " ; 
package message;

 // order request parameters 
message OrderRequest { 
    string orderId = 1 ; 
    int64 timeStamp = 2 ; 
}

 // order information 
message OrderInfo { 
    string OrderId = 1 ; 
    string OrderName = 2 ; 
    string OrderStatus = 3 ; 
}

  Compile proto file

  Compile the .proto file through the proto compilation command to automatically generate the Go language file of the corresponding structure. The compilation command is as follows:

protoc ./message.proto --go_out=./

Protobufg format data combined with RPC

  Definition of service :

  To make an RPC remote procedure call and implement the method of calling a remote server, there must be a service first. In this case, define a service that provides order query function, named OrderService, and provide order information query method for remote call. The detailed services and methods are defined as follows:

type OrderService struct {
}

func (this *OrderService) GetOrderInfo(request message.OrderRequest, response *message.OrderInfo) error {
    orderMap := map[string]message.OrderInfo{
        "201907300001": message.OrderInfo{OrderId: "201907300001", OrderName: "衣服", OrderStatus: "已付款"},
        "201907310001": message.OrderInfo{OrderId: "201907310001", OrderName: "零食",Order status:" Paid " },
         " 201907310002 " : message.OrderInfo {OrderId: " 201907310002 " , OrderName: " Food " , OrderStatus: " Unpaid " }, 
    } 
    current: = time.Now (). Unix ()
     if (request .TimeStamp> current) {
         * response = message.OrderInfo {OrderId: " 0 " , OrderName: "" , OrderStatus: " Order information is abnormal "}
    } else {
        result := orderMap[request.OrderId]
        if result.OrderId != "" {
            *response = orderMap[request.OrderId]
        } else {
            return errors.New("server error")
        }
    }
    return nil
}

  In the method definition of the service, orderMap is used to simulate the initial order database to facilitate case query and display. The GetOrderInfo method has two parameters, the first is message.OrderRequest, as the parameter passed by the caller, and the second is message.OrderInfo, as the parameter returned by the call. Through the two parameters here, the above will pass .proto Defined and automatically generated Go language structure data are combined.

  Registration and processing of services

  After the service is defined, you need to register the service to the RPC framework and enable the HTTP request monitoring process. This part of the code is consistent with the previous RPC server implementation logic, and the specific implementation is as follows:

func main() {

    orderService := new(OrderService)

    rpc.Register(orderService)

    rpc.HandleHTTP()

    listen, err := net.Listen("tcp", ":8081")
    if err != nil {
        panic(err.Error())
    }
    http.Serve(listen, nil)
}

  RPC client call implementation

  On the client, in addition to the logic that the client normally accesses the remote server, it also needs to prepare the request data message.OrderInfo that the client needs to pass. The specific implementation is as follows:

func main() {
    client, err := rpc.DialHTTP("tcp", "localhost:8081")
    if err != nil {
        panic(err.Error())
    }
    timeStamp := time.Now().Unix()
    request := message.OrderRequest{OrderId: "201907300001", TimeStamp: timeStamp}
    var response *message.OrderInfo
    err = client.Call("OrderService.GetOrderInfo", request, &response)
    if err != nil {
        panic(err.Error())
    }
    fmt.Println(*response)
}

operation result

 

Guess you like

Origin www.cnblogs.com/xiangxiaolin/p/12749196.html