小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

rpc协议与http协议简述

微服务,rpc,http,网络协议 额外说明

收录于:17天前

http协议

HTTP(超文本传输​​协议)是用于在计算机之间传输超文本的应用层协议。它是 Web 应用程序中最常用的协议,用于在客户端和服务器之间传输数据。

HTTP 超文本传输​​协议教程

从定义上看,http可以看作是传输超文本文件。这里的范围很广,比如html文件、xml文件、字符串、数字、视频、图片等。总之,凡是以流形式存在的文件都可以通过http协议进行传输。 。一般来说,HTTP传输的主体是流,字节流(文件、视频)、字符流(各种数据),字符串往往表示为字符串,通过统一的序列化和反序列化规则进行恢复和压缩。

http协议以B/S或C/S架构存在,是一种新型的客户端(请求)和服务器(响应)方式。因此,计算器通信时,必须有一台机器作为服务器,时刻监听请求,等待客户端请求数据。 。客户端和服务器通过http规定的解码和编码规则来保证传输数据的一致性。

监听请求的服务器称为Web服务器,发送请求的客户端称为Web浏览器。浏览器是指可以发送http请求的一类应用程序。有很多封装好的http库可以直接使用,比如Ajax、axios等,熟悉http协议的也可以自己封装工具库。

一个http请求一般包含如下部分:
在这里插入图片描述
浏览器的开发者模式,对http请求的命名为xhr,如下

在这里插入图片描述

综上所述,http协议主要用于传输不同计算机上产生的数据。

在网络通信的发展中,仅仅用来传输数据的http协议已经不能满足需要了。如果需要某台计算机的运行结果,在使用http协议时需要等待其操作完成,封装数据,然后发送;那么有没有可能,可以在其他计算机上直接调用请求计算机的线程,使其运行结果直接返回到目标计算机,而不需要封装数据。于是rpc协议就诞生了。

rpc

RPC(Remote procedure Call)是一种计算机通信协议,用于不同计算机或进程之间的远程调用。它允许计算机程序通过网络请求另一台计算机上的服务或功能,就像调用本地功能一样。

在通信的不断发展中,rpc协议实现了进程的调用,在其他计算机上调用目标计算机的线程,实现内存共享。该协议允许在一台计算机上运行的程序调用另一台计算机上的子例程,而程序员无需另外对交互进行编程。

rpc相关问题

在RPC中,客户端程序向服务器程序发送请求消息,服务器程序接收请求消息并执行相应的操作,然后将结果返回给客户端。这个过程对于客户端来说是透明的,就像调用本地函数一样,不需要关心底层的网络通信细节。

RPC协议通常包括以下关键组件:

  1. 通信协议:定义了客户端与服务器之间的通信规则,如数据传输格式、编码方式、网络传输协议等。常见的通信协议有HTTP、TCP、UDP等。

  2. 接口定义语言(IDL):用于定义客户端和服务器之间的接口和数据结构。 IDL提供了统一的语法和语义,使得不同编程语言的程序可以互相调用。

  3. 序列化和反序列化:将数据结构转换为字节流进行传输,或者将接收到的字节流转换为数据结构。序列化和反序列化是RPC协议中的重要环节,用于在网络中传输数据。

  4. 代理和存根:客户端和服务器分别使用代理和存根来隐藏底层网络通信细节。客户端的代理负责将函数调用转换为网络请求并发送给服务器;服务器的stub负责接收请求,执行相应的操作,并将结果返回给客户端。

RPC协议可用于构建分布式系统,连接不同的计算机或进程,实现跨网络的函数调用。常见的RPC框架有gRPC、Apache Thrift、Apache Dubbo等。

远程过程调用教程

rpcx

rpcx官方文档

rpcx 是一个和 grpc 一样流行的 RPC 框架。它更加轻量级,更适合原生RPC使用。

rpcx时国人开发的文档丰富就不再赘述了,可以移步开发手册rpcx快速入门

大致分为三步:

  1. 需要调用线程和方法
  2. 服务器程序
  3. 客户程序

案例如下server为服务端程序,client为客户端程序,service为服务线程。
在这里插入图片描述

  • service服务线程方法
package service

import (
	"context"
)

// 主程序的方法及数据
type Param struct {
    
	A, B int
	C    string
}

type Calculate int

// 返回数据
type Result struct {
    
	D int
}

// 计算方法
func (t *Calculate) Compute(cxt context.Context, args *Param, reply *Result) error {
    
	if args.C == "+" {
    
		reply.D = args.A + args.B
	} else if args.C == "-" {
    
		reply.D = args.A - args.B
	} else if args.C == "*" {
    
		reply.D = args.A * args.B
	} else if args.C == "/" {
    
		reply.D = args.A / args.B
	} else {
    
		reply.D = 0
	}
	return nil
}


服务比较简单。定义一个类写法,Param为参数,Result为返回数据。

这里需要注意的是,RPC调用的方法的参数和返回值必须来自服务的方法类,通过远程调用接收时不能自定义。只是在使用grpc时,参数和返回值只能来自pb文件,即使它们是完全定制的且一致的。

定义了Calculate 类有Compute方法传入参数和返回值,一般情况下,第一个参数是context.Context,第二个参数是参数,第三个参数是返回值。方法体就是根据表示进行加减乘除计算了。

  • server服务端程序
package main

import (
	"rpctest/service"

	"github.com/smallnest/rpcx/server"
)

// rpc服务器注册
func main() {
    
	s := server.NewServer()
	s.RegisterName("xiaoxu", new(service.Calculate), "")
	s.Serve("tcp", ":8972")
}

创建服务器,将服务注册到服务器并为其指定别名。

  • client客户端
package main

import (
	"context"
	"flag"
	"fmt"
	"log"

	"rpctest/service"

	"github.com/smallnest/rpcx/client"
)

var (
	addr = flag.String("addr", "localhost:8972", "server address")
)

func main() {
    
	flag.Parse()
	// 直接连接rpc服务器,连接会话
	d, err := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
	if err != nil {
    
		log.Fatalf("failed to call: %v", err)
	}
	// 获取客户端接口
	xclient := client.NewXClient("xiaoxu", client.Failtry, client.RandomSelect, d, client.DefaultOption)
	defer xclient.Close()
	//接口方法参数
	args := &service.Param{
    A: 10, B: 8, C: "+"}
	var reply service.Result
	//客户端接口调用方法
	err = xclient.Call(context.Background(), "Compute", args, &reply)
	if err != nil {
    
		log.Fatalf("failed to call: %v", err)
	}
	fmt.Printf("调用rpc的结果为:%d", reply.D)
}

创建rpc连接会话,通过别名获取连接到服务端的客户端,通过客户端创建接口,一般调用方法使用Call方法,第一个参数是context.Context,第一个参数是要调用的方法名称,第三个参数是服务参数,第四哥参数是服务返回值。

启动服务端
在这里插入图片描述
调用客户端
在这里插入图片描述

在此情况下,服务中定义一的任意类,参数与返回值均可以在客户端被调用,如下,在service再定义一个方法:

type ResultStr struct {
    
	Str string
}

func (t *Calculate) Hello(cxt context.Context, args *Param, reply *ResultStr) error {
    
	reply.Str = fmt.Sprintf("连接的三个参数分别为%d,%d,%s", args.A, args.B, args.C)
	return nil
}

由于它们属于同一个类,所以连接会话是相同的,接口也是相同的,所以可以直接在客户端调用。

server

// hello函数
var replay1 service.ResultStr
xclient.Call(context.Background(), "Hello", args, &replay1)
fmt.Println(replay1.Str)

在这里插入图片描述

除了Call方法同步获取返回结果外,也提供了Go异步获取返回结果,此处不再赘述。

注册中心

使用rpc时经常会用到注册中心功能。对于分布式部署,每台主机的IP不同,但方法名相同,因此可以通过方法名来调用,这就需要用到注册中心功能。

在之前的服务器会话是点对点连接,未使用注册中心,点对点是最简单的一种注册中心的方式,事实上没有注册中心,客户端直接得到唯一的服务器的地址,连接服务。也就是使用NewPeer2PeerDiscovery方法。

d := client.NewPeer2PeerDiscovery("tcp@"+*addr, "")
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
defer xclient.Close()

但是有若干台服务器,且是分布式的就不再实用了,需要实用注册中心,常见的注册中心有ZooKeeper,Etcd,Consul等。

rpcx默认的实用配置方式完成注册中心功能。只需启用相关功能配置插件即可。

在这里插入图片描述

实用的etcd注册中心的服务器端变成

// go run -tags etcd server.go
func main() {
    
    flag.Parse()

    s := server.NewServer()
    addRegistryPlugin(s)

    s.RegisterName("Arith", new(example.Arith), "")
    s.Serve("tcp", *addr)
}

func addRegistryPlugin(s *server.Server) {
    

    r := &serverplugin.EtcdRegisterPlugin{
    
        ServiceAddress: "tcp@" + *addr,
        EtcdServers:    []string{
    *etcdAddr},
        BasePath:       *basePath,
        Metrics:        metrics.NewRegistry(),
        UpdateInterval: time.Minute,
    }
    err := r.Start()
    if err != nil {
    
        log.Fatal(err)
    }
    s.Plugins.Add(r)
}

客户端连接方式改为注册中心连接。客户端需要设置EtcdDiscovery插件,设置etcd集群的basepath和地址。

// go run -tags etcd client.go
d := client.NewEtcdDiscovery(*basePath, "Arith",[]string{
    *etcdAddr}, nil)
xclient := client.NewXClient("Arith", client.Failtry, client.RandomSelect, d, client.DefaultOption)
defer xclient.Close()

go rpc开发指南

Go RPC 开发指南

地鼠文档

. . .

相关推荐

额外说明

设计模式-备忘录模式

备忘录模式 备忘录模式是什么? 备忘录模式解决什么问题? 备忘录模式实现 备忘录模式是什么? 在不破坏封装性的前提下,捕获一个对的的内部状态,并在该对象之外保持这个状态。这样以后就可将该对象恢复到原先保持的状态 备忘录模式解决什么问题? 如游戏打Boss

额外说明

零基础学Python之运算符的使用(手把手带你做牛客网python代码练习题)

文章目录 一、前言 二、运算符的分类 1、算数运算符 2、赋值运算符 3、复合赋值运算符 4、比较运算符 5、逻辑运算符 三、牛客网代码练习 1、 牛牛的加减器 2、乘法与幂运算 3、除法与取模运算 -作者简介:在校大学生一枚,Java领域新星创作者,J

额外说明

数据结构——二分查找法

二分查找法(Binary Search)是一种高效的查找算法,通常用于在已排序的数组或列表中查找特定的目标值。这个算法的基本思想是不断将查找范围缩小为原来的一半,直到找到目标值或确定目标值不存在。 二分查找是一种在每次比较之后将查找空间一分为二的算法。每

额外说明

从业务层的代码出发,去排查通用框架代码崩溃的问题

目录 1、问题说明 1.1、Release下崩溃,Debug下很难复现 1.2、用Windbg打开dump文件,发现崩溃在通用的框架代码中

额外说明

Windows PowerShell中成功进入conda虚拟环境

本人操作系统是Windows10(输入命令cmd或在运运行中输入winver查看) 在cmd命令行中大家都很熟悉,很方便进入到指定创建了的虚拟环境中,那么在PowerShell中怎么进入呢? 比如在VSCode中的TERMINAL使用的是PowerShe

额外说明

查找算法——二分查找(折半查找)

折半查找,又称为二分查找。是一种效率较高的查找算法、折半查找的算法思想是将数列按有序化(递增或递减)的顺序排列。 折半查找的基本思路是设R[low…high]是当前的查找区间,首先我们需要确定该区间的中点位置:mid = (low + high) / 2

额外说明

springMVC之拦截器

文章目录 前言 一、拦截器的配置 二、拦截器的三个抽象方法 三、多个拦截器的执行顺序 总结 前言 拦截器 一、拦截器的配置 SpringMVC中的拦截器用于拦截控制器方法的执行 SpringMVC中的拦截器需要实现HandlerInterceptor S

额外说明

yolov5模型s,l,m,x的区别

yolov5s 是什么?yolov5系列最小的模型,s是small。 适合什么情况下使用?适合在计算资源有限的设备上使用。如移动设备或边缘设备。 速度和准确率:速度最快,准确率最低。 输入分辨率:通常为640x640 # Parameters nc: 8

额外说明

《Cesium 基础知识点》- 3dtiles 模型跳转(两种方式)

加载 3dtiles 模型并跳转的两种方式。示例中使用大雁塔数据。 // 3dtiles 对象 let tileSet = new Cesium.Cesium3DTileset({ url: 'http://localhost:6701/data

额外说明

Linux【命令篇】—— Linux操作系统常用指令大全

目录 一、关机与重启指令 (1)shutdown - 关机 (2)halt - 关机 (3)reboot - 重启 (4)sync - 将内存的数据同步到磁盘 二、帮助指令 (1)man - 查看某个命令的帮助手册 (2)help - 查看某个命令的帮助

ads via 小工具