【技术分享】RPC和HTTP的关系

什么是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,微服务其实很容易理解的。

分享技术知识,如果你有什么想问或者不懂的前后端知识,可以私信我,如果对你有帮助, 可以点赞评论,如果写的不太好,也欢迎来知道一下。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怀特丶恩佐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值