Overview of net / RPC package in golang (summary)

Time:2020-1-16

RPC, or remote procedure call, is to call a service on a remote computer as if it were a local service.
My project is based on restful microservice architecture. With the communication between microservices becoming more and more frequent, more and more system resources are consumed. So I hope that I can use RPC for internal communication instead of restful for external communication. So I think of the RPC package of the golang standard library and the grpc of Google.

This article focuses on golang’s RPC package.

introduce

Golang’s RPC supports three levels of RPC: TCP, HTTP, and jsonrpc. But the RPC package of go is a unique RPC, which is different from the traditional RPC system. It only supports the interaction between the server and the client developed by go, because internally, they are encoded by gob.

The functions of go RPC can only be accessed remotely if they meet the following conditions, or they will be ignored. The detailed requirements are as follows:

  1. Function must be exported (capitalized)
  2. There must be two parameters of export type,
  3. The first parameter is the received parameter, the second parameter is the parameter returned to the customer client, and the second parameter must be of pointer type
  4. Function also has 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 able to be encoded and decoded by encoding / gob package.

Example

Take an example of HTTP.

Here is the code of 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 = args.A * args.B
  return nil
}

func (t *Arith) Divide(args *Args, quo *Quotient) error {
  if args.B == 0 {
    return errors.New("divide by zero")
  }
  quo.Quo = args.A / args.B
  quo.Rem = args.A % args.B
  return nil
}

func main() {
  arith := new(Arith)
  rpc.Register(arith)
  rpc.HandleHTTP()
  l, e := net.Listen("tcp", ":1234")
  if e != nil {
    log.Fatal("listen error:", e)
  }
  http.Serve(l, nil)
}

Analyze the above example briefly. First, instantiate an arith object arith, register the RPC service with arith, and then mount the RPC on the HTTP service. When the HTTP service is opened, we can call the RPC compliant methods in arith through the RPC client.

See the code for the client:


package main

import (
  "net/rpc"
  "log"
  "fmt"
)

type Args struct {
  A, B int
}

type Quotient struct {
  Quo, Rem int
}

func main() {
  client, err := rpc.DialHTTP("tcp", "127.0.0.1:1234")
  if err != nil {
    log.Fatal("dialing:", err)
  }

  // Synchronous call
  args := &Args{7,8}
  var reply int
  err = client.Call("Arith.Multiply", args, &reply)
  if err != nil {
    log.Fatal("arith error:", err)
  }
  fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)

  // Asynchronous call
  quotient := new(Quotient)
  divCall := client.Go("Arith.Divide", args, quotient, nil)
  replyCall := <-divCall.Done  // will be equal to divCall
  if replyCall.Error != nil {
    log.Fatal("arith error:", replyCall.Error)
  }
  fmt.Printf("Arith: %d/%d=%d...%d", args.A, args.B, quotient.Quo, quotient.Rem)
  // check errors, print, etc.
}

In brief, first connect the server side with the dialhttp method of RPC, and call method will be used to call the functions of the server side. The parameters and return values of call method have clearly expressed the overall call 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 whole RPC call logic is completed.

The above is the whole content of this article. I hope it will help you in your study, and I hope you can support developepaer more.

Recommended Today

700 million requests per second, how can Alibaba’s new generation database support?

Reading guide of Ali Mei:Lindorm is an important part of big data storage and processing in cloud operating system Feitian. Lindorm is a distributed NoSQL database developed based on HBase and oriented to the field of big data. It integrates large-scale, high-throughput, fast, flexible and real-time hybrid capabilities. It provides the world’s leading hybrid storage […]