青训营笔记之RPC框架
一、基本概念
1、为什么使用RPC?
简单应用可以通过将功能实现在一个服务或者在多个服务中,部署在一个机器上。那么,接口间调用可以是同一进程或者是本地调用。但是随着业务的发展,服务功能的增多,单体应用不能承受如此多时,需要对服务进行拆分。我们要根据业务功能划分为不同的模块,不同的模块部署到不同集群上,模块间进行通信完成功能。如将服务的管理域和执行域进行拆分。这样服务架构就更加清晰合理。在不同模块及不同服务间需要RPC才能完成通信。
2、什么是RPC?
RPC(Remote Procedure Call)是一种用于不同系统或进程之间进行远程通信的框架。它允许程序在不同的计算机或进程之间像调用本地函数一样调用远程函数,隐藏了底层通信细节。
复制代码
RPC框架提供了一种简单的方式来实现分布式系统中的通信和协作。
3、RPC的简单引入
1)、本地调用:
func multiply(x,y int)int {
return x*y
}
func main(){
e := 3
x := 10
result := multiply(x,y)//调用本地函数
fmt.Println(result)
}
复制代码
本地调用发生在同一进程中,定义multiply函数的代码和调用它的代码共享一个内存空间,故可正常执行! 但是我们无法在另一个程序调用multiply函数,因为这两个程序的内存空间相互隔离。
RPC调用的几个问题?
- 如何确定要执行的函数?
- 如何表达参数
- 如何进行网络传输
2)、RPC调用: Go语言下HttpRPC调用
server 端代码
package main
import (
"github.com/pkg/errors"
"net/rpc"
"net/http"
"fmt"
)
type Main int
type Args struct {
A int
B int
}
type Quotion struct {
Mul, Div int
}
func (m *Main)Division(arg Args,quo *Quotion) error{
if arg.B == 0{
return errors.New("devide by zero")
}
quo.Mul = arg.A / arg.B
quo.Div = arg.A % arg.B
fmt.Println("Division 被远程调用")
return nil
}
func main() {
main := new(Main)
rpc.Register(main)//注册RPC服务
rpc.HandleHTTP()
err := http.ListenAndServe(":8888",nil)
if err != nil{
fmt.Println(err.Error())
}
}
client 端代码
package main
import (
"flag"
"net/rpc"
"fmt"
"runtime"
)
type Args struct { A,B int }
type Quotion struct { Mul,Div int }
func main(){
var host string
flag.StringVar(&host,"host","127.0.0.1","主机")
flag.Parse()
//建立TCP连接
client,err:= rpc.DialHTTP("tcp",host+":8888")
if err != nil{
_, file, line, _ :=runtime.Caller(0)
fmt.Println(err.Error(),file,line)
return
}
//同步调用
arg := &Args{5,5}
var que Quotion
err = client.Call("Main.Division",arg,&que)
if err != nil{
_, file, line, _ :=runtime.Caller(0)
fmt.Println(err.Error(),file,line)
return
}
fmt.Printf("Main.Division %d/%d=%d,%d%%%d=%d\n",arg.A,arg.B,que.Mul,arg.A,arg.B,que.Div)
}
//服务端输出:
Division 被远程调用
//客户端输出:
Main.Division 5/5=1,5%5=0
二、分层设计
1、核心三层
- 编解码层:客户端和服务端通过同一份IDL文件生成不同语言的codeGen
- 协议层: 规范了数据在网络中的传输内容和格式
- 网络传输层:主要是用SocketAPI进行通信,其中SocketAPI位于应用层和传输层之间
三、关键指标
1、稳定性
- 熔断:保护调用方,防止被调用的服务出现问题而影响整个链路
- 限流:保护被调用方,防止大流量把服务压垮
- 超时控制:当下游服务因为某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放服务器资源,避免浪费资源
2、可延展性
能够提供足够多的扩展点,比如:
- 中间件
- Option
- 编解码层和协议层的扩展
- 支持扩展代码生成工具
- 支持自行添加更多的网络传输层协议
3、高性能
- 高吞吐
- 低延迟
- 多路复用:允许客户端通过单个连接向服务器发送多个请求,并同时接受多个响应