Go Diary-Reverse RPC

background

Normal RPC is based on the C/S structure. The RPC server corresponds to the network server, and the RPC client corresponds to the network client. But for some special scenarios, such as providing an RPC service on the company's intranet, but the extranet cannot connect to the intranet server. At this time, we can refer to a technology similar to reverse proxy, first actively link from the internal network to the TCP server of the external network, and then provide RPC services to the external network based on the TCP link.

Declare interface

type HelloService struct {}

func (p *HelloService) Hello(request string, reply *string) error {
    *reply = "hello:" + request
    return nil
}

Reverse RPC service

func main() {
    rpc.Register(new(HelloService))

    for {
        conn, _ := net.Dial("tcp", "localhost:1234")
        if conn == nil {
            time.Sleep(time.Second)
            continue
        }

        rpc.ServeConn(conn)
        conn.Close()
    }
}

Intranet services of reverse RPC will no longer actively provide TCP monitoring services, but will first actively connect to the other party's TCP server. Then provide RPC service to the other party based on each established TCP link.

RPC client

The RPC client needs to provide a TCP service at a public address to accept connection requests from the RPC server:

func main() {
    listener, err := net.Listen("tcp", ":1234")
    if err != nil {
        log.Fatal("ListenTCP error:", err)
    }

    clientChan := make(chan *rpc.Client)

    go func() {
        for {
            conn, err := listener.Accept()
            if err != nil {
                log.Fatal("Accept error:", err)
            }

            clientChan <- rpc.NewClient(conn)
        }
    }()

    doClientWork(clientChan)
}

When each link is established, the RPC client object is constructed based on the network link and sent to the clientChan pipeline.

The operation of the client to execute the RPC call is completed in the doClientWork function:

func doClientWork(clientChan <-chan *rpc.Client) {
    client := <-clientChan
    defer client.Close()

    var reply string
    err = client.Call("HelloService.Hello", "hello", &reply)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(reply)
}

First, get an RPC client object from the pipeline, and use the defer statement to specify that the client is closed before the function exits. Then perform normal RPC calls.

Guess you like

Origin blog.csdn.net/qq_32198277/article/details/85989607
RPC
RPC