RPC调用初识
什么是RPC远程调用?
远程调用会遇到的问题:
1.call id 的映射
2.序列化和反序列化
3.网络传输
为什么一个函数,要放在另一台服务器上面,在本地跑不是更好吗?
当电商系统,有一段逻辑是扣减库存了,但是库存服务是一个独立的系统或者说服务,这就是涉及到网络了,可以做成一个web服务来
1.函数的调用一般都是通过这个二进制数据传输,例如json和protobuf序列化数据
2.需要将本地的内存对象序列化,另一个服务反序列化才能调用
搞这么麻烦直接全部用json格式化不行吗?,这种做法在浏览器和gin服务之间是可行的,但是如果是一个大型的分布式系统,大量的调用不可以维护
大体的网络流程客户端,服务端
序列化反序列化是可以选择的,不一定要采用json,xml。选择很多
网络传输调用过程大部分是基于tcp的封装的协议,例如http,socket。grpc是基于http2.0的,1.0的话一次的不好的,性能不如长连接
Demo 样例 使用http协议做的rpc调用
server端
func main() {
http.HandleFunc("/add", func(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm() // 解析参数
fmt.Println("path: ", r.URL.Path)
a, err1 := strconv.Atoi(r.Form["a"][0])
if err1 != nil {
http.Error(w, "Invalid parameter 'a'", http.StatusBadRequest)
return
}
b, err2 := strconv.Atoi(r.Form["b"][0])
if err2 != nil {
http.Error(w, "Invalid parameter 'b'", http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/json")
Jdata, _ := json.Marshal(map[string]int{"data": a + b})
w.Write(Jdata)
})
http.ListenAndServe(":8000", nil)
}
client端
type ResponseData struct {
Data int `json:"data"`
}
func Add(a, b int) int {
// 构建 URL
url := fmt.Sprintf("http://127.0.0.1:8000/add?a=%d&b=%d", a, b)
// 发起 HTTP GET 请求
res, err := http.Get(url)
if err != nil {
fmt.Println("Error making GET request:", err)
return 0
}
defer res.Body.Close()
// 读取响应体
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return 0
}
// 打印响应体
fmt.Println(string(body))
// 解析 JSON 响应
rspData := ResponseData{}
err = json.Unmarshal(body, &rspData)
if err != nil {
fmt.Println("Error unmarshalling JSON:", err)
return 0
}
return rspData.Data
}
func main() {
fmt.Println(Add(1, 2))
}