golang RPC包原理和使用详细介绍

目录
  • 工作流程
  • 工作模式
    • http模式
    • 服务器模式

本篇文章旨在通过学习rpc包和github上的一个rpc小项目,熟悉和学习golang中各个包的使用

工作流程

通过阅读官方文档,了解了rpc的基本工作模式

  • 第一步,建立一个用于远程调用的包,存放仅供远程调用使用的方法和类型-
  • 第二步,实例化包的对象,并在rpc中注册该包,以便之后的调用
  • 第三步,建立一个服务端,接收客户端的请求,使用编码器解析请求后,根据请求中的方法和参数,调用第二步注册的实例的方法,然后使用编码器把返回值加密后,返回给客户端
  • 第四步,建立一个客户端,连接服务端,成功后,向连接发送使用编码器加密后的数据,然后等待服务端响应(同步或异步)。响应成功后,使用编码器解析服务端返回的数据

第三步第四步中,多次用到的编码器,是rpc包的关键。默认情况下,rpc包使用的是go特有的encoding/gob包进行数据的编码和解码。但是当我们服务端和客户端使用了不同的语言时,若加密方法无法兼容,就会出现问题,所以rpc包支持自定义编码器。

工作模式

go的rpc除了支持常规常规的tpc+端口的远程调用方式,也支持基于http的远程调用实现。但是,我都用rpc了,还用个毛的http形式。不过作为一种形式,我们出于礼貌的简单了解下。

http模式

官方文档的例子,就是使用的http形式的rpc,如下

服务端

//实例化rpc远程调用的方法所属对象
arith := new(Arith)
//注册对象
rpc.Register(arith)
//把rpc监听 对应到http处理器。即指定http请求addr+port时,调用的方法
rpc.HandleHTTP()
//获取监听地址
l, e := net.Listen("tcp", ":1234")
if e != nil {
	log.Fatal("listen error:", e)
}
//开启一个go程,持续处理监听数据
go http.Serve(l, nil)

客户端

//连接 rpc的http服务端
client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
if err != nil {
	log.Fatal("dialing:", err)
}
//同步调用
// 实例化rpc传入参数
args := &server.Args{7,8}
//声明rpc 回复参数。传入和回复参数,必须与调用方法中的参入类型一致
var reply int
//调用rpc注册的方法
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
	log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
//或:异步调用
// Asynchronous call
quotient := new(Quotient)
divCall := client.Go("Arith.Divide", args, quotient, nil)
replyCall := <-divCall.Done	// will be equal to divCall

从上面的代码可以看到,请求服务端时,需要客户端在服务器发起http请求,如果直接在浏览器或者其他工具发起http请求则报错,因为此时rpc.HandleHTTP方法指定的默认方法,使用的是默认gob编码器,且只接收connect类型的请求。查看源代码,如下

直接发起的http请求,无法使用go独有的gob包编码,rpc服务端也就无法使用默认gob包解码。

所以我们要写一个新的方法代替rpc.HandleHTTp,把http请求绑定到一个使用其他解码器的方法上,如下

//注册路由和对应的handler
http.HandleFunc("/json", func(rw http.ResponseWriter, r *http.Request) {
//声明一个客户端连接对象
var conn io.ReadWriteCloser = struct {
      io.Writer
      io.ReadCloser
   }{
      ReadCloser: r.Body,
      Writer:     rw,
   }
//也可以使用如下方法获取接管客户端连接,http处理器不在管理该链接,使用完毕后需要自行关闭链接
// conn, _, err := rw.(http.Hijacker).Hijack()
  // if err != nil {
   //   log.Print("rpc hijacking fail: ", err.Error())
    //  return
   // }
   io.WriteString(conn, "HTTP/1.0 rpc-ok\n\n")
   //server.ServeConn(conn)
 //rpc.ServeRequest,指定编码器,以同步的方式处理请求一次,编码器内不关闭链接,由http服务处理。适用于http形式的请求,因为http是无状态的,每次请求都是一个新的链接
//rpc.ServeCodec,指定编码器,for循环接收客户端链接的消息,每次消息处理开启一个go程,相当于异步处理,直到客户端关闭或解码错误,跳出循环,关闭连接。适用客户端,一次连接多次发送数据
   rpc.ServeRequest(jsonrpc.NewServerCodec(conn))})
//监听http请求
http.ListenAndServe("127.0.0.1:1234", nil)

上面代码中的==jsonrpc.NewServerCodec(conn)==是一个官方定义好的json格式的编码器。我们在http中发送数据时,只要使用json格式,就能被服务端解析

执行go文件,在post模拟url请求,如下

服务器模式

服务端

//声明和注册rpc方法对象
//获取监听信息
lis, err := net.Listen("tcp", ":8082")
	if err != nil {
		log.Fatal(err)
}
//循环读取监听到的数据
for {
	//获取一个客户端连接
   conn, err := lis.Accept()
   if err != nil {
      continue
   }
   //开启一个go程序,使用自定义编码器处理当前获取连接
   go s.Server.ServeCodec(jsonrpc.NewServerCodec(conn))
}

客户端

//连接服务端
conn, err := net.Dial("tcp", ":8082")if err != nil {
	log.Fatal(err)
}
defer conn.Close()
//使用json编码器新建客户端
client := &Client{rpc.NewClientWithCodec(jsonrpc.NewServerCodec(conn))}
//声明rpc方法中传入和输出的参数
resq := message.ArithRequest{A: 20, B: 5}
resp := message.ArithResponse{}
//调用rpc方法
err = client.Call("ArithService.Add", &resq, &resp)
log.Printf("Arith.Add(%v, %v): %v ,Error: %v", resq.A, resq.B, resp.C, err)

到此这篇关于golang RPC包原理和使用详细介绍的文章就介绍到这了,更多相关golang RPC包内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang在GRPC中设置client的超时时间

    超时 建立连接 主要就2函数Dail和DialContext. // Dial creates a client connection to the given target. func Dial(target string, opts ...DialOption) (*ClientConn, error) { return DialContext(context.Background(), target, opts...) } func DialContext(ctx context.Cont

  • Golang开发gRPC服务入门介绍

    目录 1.安装protoc 2.安装protoc的Golang gRPC插件 3.编写proto文件 4.生成gRPC代理代码 5.编写gRPC服务端程序 6.编写gRPC客户端程序 7.运行程序 gRPC是Google发起的一个开源RPC框架,使用HTTP/2传输协议,使用Protocol Buffers编码协议,相比RESTful框架的程序性能提高不少,而且当前流行的编程语言基本都已经支持. Golang开发gRPC应用程序的套路也已经很清晰,这篇文章就来做一个简单的介绍,算是入门. 1.安

  • Golang实现gRPC的Proxy的原理解析

    背景 gRPC是Google开始的一个RPC服务框架, 是英文全名为Google Remote Procedure Call的简称. 广泛的应用在有RPC场景的业务系统中,一些架构中将gRPC请求都经过一个gRPC服务代理节点或网关,进行服务的权限现在,限流,服务调用简化,增加请求统计等等诸多功能. 如下以Golang和gRPC为例,解析gRPC的转发原理. gRPC Proxy原理 基本原理如下 基于TCP启动一个gRPC代理服务 拦截gRPC框架的服务映射,能将gRPC请求的服务拦截到转发代

  • Golang gRPC HTTP协议转换示例

    gRPC HTTP协议转换 正当有这个需求的时候,就看到了这个实现姿势.源自coreos的一篇博客,转载到了grpc官方博客gRPC with REST and Open APIs. etcd3改用grpc后为了兼容原来的api,同时要提供http/json方式的API,为了满足这个需求,要么开发两套API,要么实现一种转换机制,他们选择了后者,而我们选择跟随他们的脚步. 他们实现了一个协议转换的网关,对应github上的项目grpc-gateway,这个网关负责接收客户端请求,然后决定直接转发

  • golang使用grpc+go-kit模拟oauth认证的操作

    我们使用grpc对外的接口,进行服务,模拟对外认证的接口 首先我们要了解oauth的基本认证过程 第三方的服务端,在oauth2.0中作为一个客户端的身份,进行请求数据. 用户进行选择第三方的登陆,比如选择到某一个第三方的平台进行登陆,则会跳转到第三方登陆平台 用户输入用户名密码,在第三方平台进行登陆,,如果登陆成功,则返回code. 客户端,也就是我们想要登陆的网站,将会读取code,并且将会携带这个code,和第三方网站所颁发的密码,进行请求token,如果code和注册时所得到的密码,都验

  • Golang原生rpc(rpc服务端源码解读)

    创建rpc接口,需要几个条件 方法的类型是可输出的 方法的本身也是可输出的 方法必须有两个参数,必须是输出类型或者是内建类型 方法的第二个参数是指针类型 方法返回的类型为error rpc服务原理分析 server端 服务注册 处理网络调用 服务注册 通过反射处理,将接口存入到map中,进行调用 注册服务两个方法 func Register (rcvr interface{}) error {} func RegisterName (rcvr interface{} , name string)

  • golang实现简单rpc调用过程解析

    目录 基本概念 RPC通信过程 RPC 具体实现 server端 客户端 基本概念 RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的服务,该协议允许运行于一台计算机的程序调用另一台计算机的子程序,而程序员无需额外地为这个交互作用编程,RPC最直接的作用就是微服务. RPC通信过程 RPC的通信过程网上介绍很多,这里就不在单独介绍了,具体过程如下:1.Client以本地调用的方式发起调用:2.Client stub收到调用后负责将被调用的方

  • golang下grpc框架的使用编写示例

    目录 1. 什么是grpc和protobuf 1.1 grpc 1.2 protobuf 2.go下grpc 2.1官网下载protobuf工具 2.2 下载go的依赖包 2.3 编写proto文件 2.4 生成hello.pb.proto文件 2.5 编写server端代码 2.6 编写client端代码 2.7 python和go相互调用实践(跨语言调用) 1. 什么是grpc和protobuf 1.1 grpc gRPC是一个高性能.开源和通用的RPC框架,面向移动和HTTP/2设计. 目

  • Golang语言实现gRPC的具体使用

    目录 gRPC 的特点 使用 gRPC 定义服务端 使用 gRPC 的客户端 gRPC 是通信协议基于 HTTP/2,支持多语言的 RPC 框架,使用 Protobuf 作为它的接口设计语言(IDL),可以通过 protoc 工具生成 Golang 语言的结构体. RPC:Remote Procedure Call 的缩写,译为远程过程调用(也可译为远程方法调用或远程调用),它是计算机通信协议.该协议可以实现调用远程服务就像调用本地服务一样简单,无需关心跨网络,跨平台,跨语言等问题. gRPC

  • golang RPC包原理和使用详细介绍

    目录 工作流程 工作模式 http模式 服务器模式 本篇文章旨在通过学习rpc包和github上的一个rpc小项目,熟悉和学习golang中各个包的使用 工作流程 通过阅读官方文档,了解了rpc的基本工作模式 第一步,建立一个用于远程调用的包,存放仅供远程调用使用的方法和类型- 第二步,实例化包的对象,并在rpc中注册该包,以便之后的调用 第三步,建立一个服务端,接收客户端的请求,使用编码器解析请求后,根据请求中的方法和参数,调用第二步注册的实例的方法,然后使用编码器把返回值加密后,返回给客户端

  • Python Counting Bloom Filter原理与实现详细介绍

    目录 前言 原理 一.BF 为什么不支持删除 二.什么是 Counting Bloom Filter 三.Counter 大小的选择 简单的实现 总结 前言 标准的 Bloom Filter 是一种比较简单的数据结构,只支持插入和查找两种操作.在所要表达的集合是静态集合的时候,标准 Bloom Filter 可以很好地工作,但是如果要表达的集合经常变动,标准Bloom Filter的弊端就显现出来了,因为它不支持删除操作.这就引出来了本文要谈的 Counting Bloom Filter,后文简

  • 一文彻底理解Golang闭包实现原理

    目录 前言 函数一等公民 作用域 实现闭包 闭包扫描 闭包赋值 闭包函数调用 函数式编程 总结 前言 闭包对于一个长期写 Java 的开发者来说估计鲜有耳闻,我在写 Python 和 Go 之前也是没怎么了解,光这名字感觉就有点"神秘莫测",这篇文章的主要目的就是从编译器的角度来分析闭包,彻底搞懂闭包的实现原理. 函数一等公民 一门语言在实现闭包之前首先要具有的特性就是:First class function 函数是第一公民. 简单来说就是函数可以像一个普通的值一样在函数中传递,也能

  • golang中的net/rpc包使用概述(小结)

    RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. 我的项目是采用基于Restful的微服务架构,随着微服务之间的沟通越来越频繁,消耗的系统资源越来越多,于是乎就希望可以改成用rpc来做内部的通讯,对外依然用Restful.于是就想到了golang标准库的rpc包和google的grpc. 这篇文章重点了解一下golang的rpc包. 介绍 golang的rpc支持三个级别的RPC:TCP.HTTP.JSONR

  • Android组件化原理详细介绍

    目录 什么是组件化? 为什么使用组件化? 一步步搭建组件化 1.新建模块 2.统一Gradle版本号 3.创建基础库 4.组件模式和集成模式转换 5.AndroidManifest的切换 6.*业务Application切换 组件之间的跳转 1.添加依赖 2.初始化ARouter 3.添加跳转 组件之间的数据传递 1.定义接口 2.实现接口 组件Application的动态切换 1.定义抽象类 BaseApplication 继承 Application 2.所有的组件的 Application

  • Golang分布式锁详细介绍

    目录 进程内加锁 trylock 基于redis的setnx 基于zk 基于etcd redlock 如何选择 在单机程序并发或并行修改全局变量时,需要对修改行为加锁以创造临界区.为什么需要加锁呢?可以看看下段代码: package main import ( "sync" ) // 全局变量 var counter int func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go f

  • Python包和模块的分发详细介绍

    发布Python包 上一篇介绍了如何使用别人的轮子,现在我们讨论下如何自己造轮子给别人用. 作为一个流行的开源开发项目,Python拥有一个活跃的贡献者和用户支持社区,这些社区也可以让他们的软件可供其他Python开发人员在开源许可条款下使用.这允许Python用户有效地共享和协作,从其他人已经创建的解决方案中受益于常见(有时甚至是罕见的)问题,以及可以提供他们自己的解决方案. Pypi( Python Package Index) ,公共的模块存储中心 准备 distutils 官方库dist

  • Golang Compare And Swap算法详细介绍

    目录 CAS算法(compare and swap) CAS是如何运行的 Go中的CAS源码 CAS的缺陷 CAS算法(compare and swap) CAS算法涉及到三个操作数 需要读写的内存值V 进行比较的值A 拟写入的新值B 当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作).一般情况下是一个自旋操作,即不断的重试. CAS算法(Compare And Swap),是原子操作的一种, CAS算法是一种有名的无锁算法.无

  • java RMI详细介绍及实例讲解

    java本身提供了一种RPC框架--RMI(即RemoteMethodInvoke远程方法调用),在编写一个接口需要作为远程调用时,都需要继承了Remote,Remote接口用于标识其方法可以从非本地虚拟机上调用的接口,只有在"远程接口"(扩展java.rmi.Remote的接口)中指定的这些方法才可远程使用,下面通过一个简单的示例,来讲解RMI原理以及开发流程: 为了真正实现远程调用,首先创建服务端工程rmi-server,结构如下: 代码说明: 1.User.java:用于远程调用

  • Go 实现热重启的详细介绍

    最近在优化公司框架 trpc 时发现了一个热重启相关的问题,优化之余也总结沉淀下,对 go 如何实现热重启这方面的内容做一个简单的梳理. 1.什么是热重启? 热重启(Hot Restart),是一项保证服务可用性的手段.它允许服务重启期间,不中断已经建立的连接,老服务进程不再接受新连接请求,新连接请求将在新服务进程中受理.对于原服务进程中已经建立的连接,也可以将其设为读关闭,等待平滑处理完连接上的请求及连接空闲后再行退出.通过这种方式,可以保证已建立的连接不中断,连接上的事务(请求.处理.响应)

随机推荐