RPC


RPC

什么是RPC?

RPC 是远程过程调用(Remote Procedure Call)的缩写形式。

RPC 是指计算机 A 上的进程,调用另外一台计算机 B 上的进程,其中 A 上的调用进程被挂起,而 B 上的被调用进程开始执行,当值返回给 A 时,A 进程继续执行。

调用方可以通过使用参数将信息传送给被调用方,而后可以通过传回的结果得到信息。而这一过程,对于开发人员来说是透明的。

  • 远程过程调用采用客户机/服务器(C/S)模式。
  • 请求程序就是一个客户机,而服务提供程序就是一台服务器。
  • 和常规或本地过程调用一样,远程过程调用是同步操作,在远程过程结果返回之前,需要暂时中止请求程序。
  • 使用相同地址空间的低权进程或低权线程允许同时运行多个远程过程调用。

RPC面临的问题

  1. 将原本本地的函数放到另一个服务器上运行,会面临很多问题。
  2. Call的id映射
  3. 序列化与反序列化
  4. 网络传输

RPC和微服务

  1. 每个服务都被封装成进程。彼此“独立”。
  2. 进程和进程间,可以使用不同的语言实现。

使用Gin框架创建简单Web服务

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.Writer.Write([]byte("hello world!"))
    })
    r.Run(":8080")
}

RPC基础实现

Server

package main

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

// 0.定义类对象,绑定类方法
type World struct {
}

func (w *World) HelloWorld(name string, resp *string) error {
    *resp = "hello " + name
    return nil
}

func main() {
    // 1.注册RPC服务,绑定对象方法
    err := rpc.RegisterName("hello", new(World))
    if err != nil {
        fmt.Println("rpc error!")
        return
    }
    // 2.设置监听
    server, err := net.Listen("tcp", "127.0.0.1:8080")
    if err != nil {
        fmt.Println("Listen error!")
        return
    }
    defer server.Close()
    for {
        // 3.建立连接
        conn, err := server.Accept()
        if err != nil {
            fmt.Println("Conn error!")
            return
        }
        defer conn.Close()
        fmt.Println("连接建立成功!")
        // 4.绑定服务
        rpc.ServeConn(conn)
    }
}

Client

package main

import (
    "fmt"
    "net/rpc"
)

func main() {
    //1.建立 rpc 连接
    conn, err := rpc.Dial("tcp", "127.0.0.1:8080")
    if err != nil {
        fmt.Println("Conn error!")
        return
    }
    //2.调用远程方法
    var reply string
    err = conn.Call("hello.HelloWorld", "zj", &reply)
    if err != nil {
        fmt.Println("Call error!")
        return
    }
    fmt.Println(reply)
}