Go简单实现RPC和gRPC的调用

RPC

RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求
服务,而不需要了解底层网络技术的协议。
简单来说,就是跟远程访问或者web请求差不多,都是一个client向远端服务器请求服务返回结果,但是web请求
使用的网络协议是http高层协议,而rpc所使用的协议多为TCP,是网络层协议,减少了信息的包装,加快了处理速
度。
golang本身有rpc包,可以方便的使用,来构建自己的rpc服务,下边是一个简单是实例,可以加深我们的理解
在这里插入图片描述

1.调用客户端句柄;执行传送参数
2.调用本地系统内核发送网络消息
3.消息传送到远程主机
4.服务器句柄得到消息并取得参数
5.执行远程过程
6.执行的过程将结果返回服务器句柄
7.服务器句柄返回结果,调用远程系统内核
8.消息传回本地主机
9.客户句柄由内核接收消息
10.客户接收句柄返回的数据

服务端

package main
import (
"net/http"
"net/rpc"
"net"
"github.com/astaxie/beego"
"io"
) //- 方法是导出的
//- 方法有两个参数,都是导出类型或内建类型
//- 方法的第二个参数是指针
//- 方法只有一个error接口类型的返回值
//
//func (t *T) MethodName(argType T1, replyType *T2) error
type Panda int;
func (this *Panda)Getinfo(argType int, replyType *int) error {
    beego.Info(argType)
   *replyType =1 +argType

return nil
}
 func main() {
//注册1个页面请求
   http.HandleFunc("/panda",pandatext)
//new 一个对象
   pd :=new(Panda)
//注册服务
//Register在默认服务中注册并公布 接收服务 pd对象 的方法
   rpc.Register(pd)
   rpc.HandleHTTP()
//建立网络监听
  ln , err :=net.Listen("tcp","127.0.0.1:10086")
  if err != nil{
  beego.Info("网络连接失败")
} 
  beego.Info("正在监听10086")
//service接受侦听器l上传入的HTTP连接,
   http.Serve(ln,nil)
} //用来现实网页的web函数
func pandatext(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w,"panda")
}

客户端

package main
import (
"net/rpc"
"github.com/astaxie/beego"
)
 func main() {
//rpc的与服务端建立网络连接
cli,err := rpc.DialHTTP("tcp","127.0.0.1:10086")
if err !=nil {
   beego.Info("网络连接失败")
} 
   var val int
//远程调用函数(被调用的方法,传入的参数 ,返回的参数)
  err =cli.Call("Panda.Getinfo",123,&val)
 if err!=nil{
    beego.Info("打call失败")
}
   beego.Info("返回结果",val)
}

GRPC

在 gRPC里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC系统类似, gRPC也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。 gRPC客户端和服务端可以在多种环境中运行和交互 -从 google内部的服务器到你自己的笔记本,并且可以用任何 gRPC支持的语言 来编写。所以,你可以很容易地用 Java创建一个gRPC服务端,用 Go、 Python、Ruby来创建客户端。此外, Google最新 API将有 gRPC版本的接口,使你很容易
地将 Google的功能集成到你的应用里。

GRPC使用 protocol buffers

gRPC默认使用protoBuf,这是 Google开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如JSON)。正如你将在下方例子里所看到的,你用 proto files创建 gRPC服务,用 protoBuf消息类型来定义方法参
数和返回类型。你可以在 Protocol Buffers文档找到更多关于 protoBuf的资料。 虽然你可以使用 proto2 (当前默认的 protocol buffers版本 ),我们通常建议你在 gRPC里使用 proto3,因为这样你可以使用 gRPC支持全部范围的
的语言,并且能避免 proto2客户端与 proto3服务端交互时出现的兼容性问题,反之亦然。

在这里插入图片描述

go语言实现GRPC远程调用

protobuf协议定义

创建一个 protobuf package,如: my_rpc_proto;
在$GOPATH/src/下创建 /my_grpc_proto/文件夹里面创建 protobuf协议文件 helloServer.proto

#到工作目录
$ CD $GOPATH/src/
#创建目录
$ mkdir grpc/myproto
#进入目录
$ cd grpc/myproto
#创建proto文件
$ vim helloServer.proto
syntax = "proto3";
package my_grpc_proto;
service HelloServer{
// 创建第一个接口
rpc SayHello(HelloRequest)returns(HelloReplay){}
// 创建第二个接口
rpc GetHelloMsg(HelloRequest)returns(HelloMessage){}
}
 message HelloRequest{
   string name = 1 ;
} 
message HelloReplay{
    string message = 1;
} 
message HelloMessage{
   string msg = 1;
}

在当前文件下,编译 helloServer.proto文件

$ protoc --go_out=./ *.proto #不加grpc插件
$ protoc --go_out=plugins=grpc:./ *.proto #添加grpc插件
#对比发现内容增加
#得到 helloServer.pb.go文件

gRPC-Server编写

package main
import (
"net"
"fmt"
"google.golang.org/grpc"
pt "demo/grpc/proto"
"context"
)
 const (
    post = "127.0.0.1:18881"
)
 //对象要和proto内定义的服务一样
type server struct{}
//实现RPC SayHello 接口
func(this *server)SayHello(ctx context.Context,in *pt.HelloRequest)(*pt.HelloReplay, error){
   return &pt.HelloReplay{Message:"hello"+in.Name},nil
} 

//实现RPC GetHelloMsg 接口
func (this *server) GetHelloMsg(ctx context.Context, in *pt.HelloRequest)(*pt.HelloMessage, error) {
   return &pt.HelloMessage{Msg: "this is from server HAHA!"}, nil
}

 func main() {
//监听网络
   ln ,err :=net.Listen("tcp",post)
if err!=nil {
   fmt.Println("网络异常",err)
}

// 创建一个grpc的句柄
srv:= grpc.NewServer()
//将server结构体注册到 grpc服务中
pt.RegisterHelloServerServer(srv,&server{})

//监听grpc服务

err= srv.Serve(ln)
if err!=nil {
   fmt.Println("网络启动异常",err)
}
}

gRPC-Client编写

package main
import (
"google.golang.org/grpc"
pt "demo/grpc/proto"
"fmt"
"context"
)
 const (
    post = "127.0.0.1:18881"
)
 func main() {
// 客户端连接服务器
conn,err:=grpc.Dial(post,grpc.WithInsecure())
if err!=nil {
fmt.Println("连接服务器失败",err)
} 


defer conn.Close()
//获得grpc句柄
c:=pt.NewHelloServerClient(conn)

// 远程调用 SayHello接口
//远程调用 SayHello接口
r1, err := c.SayHello(context.Background(), &pt.HelloRequest{Name: "panda"})
if err != nil {
fmt.Println("cloud not get Hello server ..", err)
  return
}
 fmt.Println("HelloServer resp: ", r1.Message)
 
//远程调用 GetHelloMsg接口
r2, err := c.GetHelloMsg(context.Background(), &pt.HelloRequest{Name: "panda"})
if err != nil {
fmt.Println("cloud not get hello msg ..", err)
  return
} 
fmt.Println("HelloServer resp: ", r2.Msg)
}

#先运行 server,后运行 client
#得到以下输出结果
HelloServer resp: hellopanda
HelloServer resp: this is from server HAHA!
#如果反之则会报错

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RPC(Remote Procedure Call)和gRPC(Google Remote Procedure Call)都是用于远程过程调用的协议。它们允许客户端应用程序像调用本地函数一样调用远程函数,从而简化了分布式系统中的通信。 RPC是一种通用的协议,可以使用不同的编码格式和传输协议来实现RPC的编解码过程是在客户端和服务器端之间进行的,这意味着它可以使用不同的编码格式来传输数据。 gRPC是由Google开发的一种基于RPC的框架,它使用Protocol Buffers作为默认的编码格式,并且使用HTTP/2作为传输协议。gRPC提供了强类型的接口定义语言(IDL),可以用来定义RPC服务的接口和消息格式,从而使得客户端和服务器端可以生成相应的代码来进行通信。 相比于RPCgRPC具有以下优势: 1. 高效的编码格式:Protocol Buffers是一种高效的二进制编码格式,它可以大幅减少数据传输的大小,从而提高网络带宽的利用率。 2. 高效的传输协议:HTTP/2是一种高效的传输协议,它支持多路复用和头部压缩等特性,可以减少网络延迟和带宽占用。 3. 强类型的IDL:gRPC提供了一种强类型的IDL,可以用来定义服务接口和消息格式,从而使得客户端和服务器端可以生成相应的代码来进行通信,减少了手动编写和解析请求和响应的工作量。 4. 多语言支持gRPC支持多种编程语言,包括C++、Java、Python、Go等,可以在不同的平台上进行通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值