什么是RPC,什么是HTTP,他们关系是什么?
RPC
RPC(Remote Procedure Call)中文名为远程过程调用,有点类似CS结构,客户端携带参数向服务端请求,服务端将参数通过一些转化,例如Java就是将参数进行反射从而实现对象的调用,将调用结果传回给客户端。
是不是觉得很官方,通俗一点来讲,就是客户端调用服务端的方法,然后接收服务端的返回值。
HTTP
HTTP(Hyper Text Transfer Protocol)中文名为超文本传输协议,这又是什么呢?也是CS结构,客户端发送HTTP Request请求给服务端,服务端接收后返回HTTP Response给客户端。
这两者有什么联系呢?
其实本来就没什么关系,RPC是一种技术的名称,HTTP是一种协议的名称,他们并不是同一个维度的东西,但是呢,RPC可以通过HTTP来实现,比如我们常见的一个RPC框架grpc就是通过HTTP去实现的。
那么有HTTP为什么还要用RPC呢?
因为http协议太过于繁重,所以如果单纯使用http进行网络传输,会有一定的网络带宽冗余现象,所以就有些人会通过Socket自己去写一套RPC框架,而不是单纯使用HTTP协议。常见的用Socket实现的RPC框架有Dubbo。
学RPC有什么用
在微服务方面来说,RPC一般用于后端业务的调用,当你将两个服务启动后,他们处于不同的进程,如果想让他们进行通信,必须使用Socket进行编程。(重点:进程之间的通信使用的是Socket)
如何去实现一个RPC框架
最简单的办法就是封装一个HTTP请求,将RPC协议规定一下,就可以实现,就比如我通过Golang+Consul封装的一个调用方法。
func Call(c registry.Registry, serviceName string, path string, request *Result.Result) (*Result.Result, error) {
result := Result.NewResult()
//注册中心获取服务,path方法,request参数,response
/**
服务名
方法名
参数
参数类型
*/
service, _ := c.GetService(serviceName)
next := selector.Random(service)
node, _ := next()
var req *http.Request
var err error
if request == nil {
req, err = http.NewRequest("POST", "http://"+node.Address+path, nil)
} else {
marshal, err := json.Marshal(request)
if err != nil {
return nil, err
}
buffer := bytes.NewBuffer(marshal)
req, err = http.NewRequest("POST", "http://"+node.Address+path, buffer)
}
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json;charset=UTF-8") //添加请求头
client := http.Client{}
resp, err := client.Do(req.WithContext(context.TODO()))
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
}
}(resp.Body)
if err != nil {
return nil, err
}
all, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal(all, result)
if err != nil {
return nil, err
}
return result, nil
}
type Result struct {
Code int `json:"code"`
Data map[string]interface{} `json:"data"`
IsSuccess bool `json:"is_success"`
Message string `json:"message"`
}
如果你了解过go,那么上面的代码你一定能看懂,就是一个很普通的http请求,通过服务名向Consul去请求得到服务的ip和端口,我们就可以通过http求请求这个服务,然后我们只要规定好Request和Response的传输协议也就是Result,就可以像调用本地方法一样调用。
比如下面:
response, err := call.Call(gloabl.GetConsul(), "UserService", "/favorite/action/", request)
我通过请求Consul的UserService,携带一个Request过去,最后返回的就是一个Response,使用的人是没有感知的调用到了服务,并且得到了结果。
有的人想问我,我明明是学Java的,为什么要用go来演示呢,那是因为Java的Dubbo太好用了,通过注解和配置就可以实现RPC的调用,所以没办法,懒得用Java实现。
总结
RPC其实就是一个网络请求,RPC实现可以用Socket或者HTTP,其实HTTP也属于Socket。学好RPC,微服务其实很容易理解的。
分享技术知识,如果你有什么想问或者不懂的前后端知识,可以私信我,如果对你有帮助, 可以点赞评论,如果写的不太好,也欢迎来知道一下。