2021你必须懂的RPC--分布式微服务和云计算应用的核心技术

Posted gocloudcoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021你必须懂的RPC--分布式微服务和云计算应用的核心技术相关的知识,希望对你有一定的参考价值。

大家好我是CloudCoder,云计算码农,专注分享linux/go/java等相关技术。


2021你必须懂的RPC--分布式、微服务和云计算应用的核心技术

随着分布式、微服务、云计算应用越来越火,对于程序猿来说,需要了解的东西也越来越多,概念也越来越多。今天就来聊聊这些热门技术背后的核心技术RPC--远程过程调用(Remote Procedure Call)。

http 与  rpc  的区别与联系

HTTP协议,以其中的Restful规范为代表,其优势很大。它可读性好,且可以得到防火墙的支持、跨语言的支持。但是HTTP也有其缺点,这是与其优点相对应的。首先是有用信息占比少,并且使用HTTP协议调用远程方法比较复杂,要封装各种参数名和参数值。

而良好的rpc调用是面向服务的封装,且RPC框架针对服务的可用性和效率等都做了优化。在目前推崇的分布式应用,微服务应用,云计算等面有着广泛的应用。可以理解为,远程的方法就和本地的方法无异,包括所有的过程都和本地是一样的。后面会使用代码进行讲解。

在分布式系统中,因为每个服务的边界都很小,很有可能调用别的服务提供的方法。这就出现了服务A调用服务B中方法的需求,即远程过程调用。要想让服务A调用服务B中的方法,最先想到的当然是通过http去实现,让服务B暴露接口,然后让A通过接口去调用对应的服务。

当然,基于接口的调用方式不仅可读性好,而且http请求可以通过各种防火墙,同时也很方便。但是基于这种方式存在一个明显的缺点,效率比较低,封装调用比较复杂,当前分布式,微服务比较热门,微服务就是将业务拆解为很多的小服务,那么这将存在大量的服务间调用,还使用基于接口的调用方式就不太适合了。

服务A调用服务B的过程是应用间的内部过程,牺牲可读性提升效率、易用性是可取的。基于这种思路,RPC产生了。调用方可以像调用内部接口一样调用远程的方法,而不用封装参数名和参数值等操作。

如何选择http 和  rpc呢?

根据业务场景,业务的大小进行灵活的运用。

与前端交互当然还是使用http的方式,在后端服务之间调用选择http 或者 rpc。

一般来讲中小厂多使用http方式。

大厂多使用http + rpc组合的方式。

通过代码分析两者的区别

我们实现一个简单的服务,两个整数相加,返回结果。

首先我们通过http方式实现。老样子使用Go语言做演示,技术栈为gin框架。

服务端代码:

package main

import (
 "github.com/gin-gonic/gin"
 "github.com/spf13/cast"
 "net/http"
)

func main() {
 r := gin.Default()
    //使用POST,路由为http://localhost:8080/add
 r.Handle("POST""/add", add)
 if err := r.Run(":8080"); err != nil {
  panic("err")
 }
}

func add(c *gin.Context) {
 //获取参数a的值
 a := c.PostForm("a")
 //获取参数b的值
 b := c.PostForm("b")
 //将string类型转为int类型并相加
 result := cast.ToInt(a) + cast.ToInt(b)
 //返回json形式的结果,参数为result
 c.IndentedJSON(http.StatusOK, gin.H{
  "result" : result,
 })
}

客户端代码:

package main

import (
 "fmt"
 "io/ioutil"
 "net/http"
 "net/url"
)

func main() {
    //将a = 1, b = 2传到后端
 params := url.Values{
  "a": {"1"},
  "b": {"2"},
 }
    //请求后端服务得到相应
 resp, _ := http.PostForm("http://localhost:8080/add", params)
 defer resp.Body.Close()
    //获取结果
 body, _ := ioutil.ReadAll(resp.Body)
 fmt.Println(string(body))
}

接下来我们通过rpc方式实现

服务端代码:

package main

import (
 "log"
 "net"
 "net/http"
 "net/rpc"
)

type NumbersTwo struct {
 A int
 B int
}

func main() {
 Nt := new(NumbersTwo)
 //注册服务对象
 //该对象必须是结构体对象,通过对象所属的方法暴露给调用者从而提供服务
 err := rpc.Register(Nt)
 if err != nil {
  log.Fatal(err)
 }
 //通过该函数把对象所属的方法的服务注册到http协议上,方便调用者可以利用http的方式进行数据传递
 rpc.HandleHTTP()
 //端口监听
 listen, err := net.Listen("tcp"":8080")
 if err != nil {
  panic(err.Error())
 }
 err = http.Serve(listen, nil)
 if err != nil {
  panic(err.Error())
 }
}

func (n *NumbersTwo) AddTwoNumbers(t map[string]int, result *int) error {
 *result = t["A"] + t["B"]
 return nil

客户端代码:

//client.go客户端
package main
import (
 "fmt"
 "net/rpc"
)
func main() {
 //通过http的端口监听方式连接
 client, err := rpc.DialHTTP("tcp""localhost:8080")
 if err != nil {
  panic(err.Error())
 }
 var result *int
 t := map[string]int{
  "A":1,
  "B":2,
 }
 //调用远端方法
 err = client.Call("NumbersTwo.AddTwoNumbers", t, &result)
 if err != nil {
  panic(err.Error())
 }
 fmt.Println("远程调用程序, 结果为:", *result)
}


使用rpc的方式,就像是使用本地的方法一样。比http方式更加的高效,更加的适合分布式应用和微服务。



以上是关于2021你必须懂的RPC--分布式微服务和云计算应用的核心技术的主要内容,如果未能解决你的问题,请参考以下文章

RPC协议及实现方式(分布式微服务治理的核心)

一个开源分布式微服务RPC框架 ~ 2.0版本问世

一分钟弄懂啥是分布式和微服务

分布式微服务集群概念梳理

分布式微服务必须配个日志管理系统才优秀,Exceptionless走起~~~

集群分布式微服务概念和区别