【网络协议】RPC、REST API深入理解及简单demo实现

目录

  • 一、RPC
  • 二、REST
  • 三、代码
    • 3.1 RPC demo
    • 3.2 Rest API demo

一、RPC

RPC远程过程调用Remote Procedure Call Protocol,简称RPC),像调用本地服务(方法)一样调用服务器的服务(方法)。通常的实现有 XML-RPC , JSON-RPC , 通信方式基本相同, 所不同的只是传输数据的格式.

RPC是分布式架构的核心,按响应方式分如下两种:

同步调用:客户端调用服务方方法,等待直到服务方返回结果或者超时,再继续自己的操作

异步调用:客户端把消息发送给中间件,不再等待服务端返回,直接继续自己的操作。

同步调用的实现方式有WebService和RMI。Web Service提供的服务是基于web容器的,底层使用http协议,因而适合不同语言异构系统间的调用。RMI实际上是Java语言的RPC实现,允许方法返回 Java 对象以及基本数据类型,适合用于JAVA语言构建的不同系统间的调用。

异步调用的JAVA实现版就是JMS(Java Message Service),目前开源的的JMS中间件有Apache社区的ActiveMQ、Kafka消息中间件,另外有阿里的RocketMQ。

RPC架构里包含如下4个组件:

  1. 客户端(Client):服务调用方
  2. 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数打包成网络消息,再通过网络发送给服务方
  3. 服务端存根(Server Stub):接受客户端发送过来的消息并解包,再调用本地服务
  4. 服务端(Server):真正的服务提供者。

具体实现步骤:

  1. 服务调用方(client)(客户端)以本地调用方式调用服务;
  2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;在Java里就是序列化的过程
  3. client stub找到服务地址,并将消息通过网络发送到服务端;
  4. server stub收到消息后进行解码,在Java里就是反序列化的过程;
  5. server stub根据解码结果调用本地的服务;
  6. 本地服务执行处理逻辑;
  7. 本地服务将结果返回给server stub;
  8. server stub将返回结果打包成消息,Java里的序列化;
  9. server stub将打包后的消息通过网络并发送至消费方
  10. client stub接收到消息,并进行解码, Java里的反序列化;
  11. 服务调用方(client)得到最终结果。

RPC框架的目标就是把2-10步封装起来,把调用、编码/解码的过程封装起来,让用户像调用本地服务一样的调用远程服务。要做到对客户端(调用方)透明化服务, RPC框架需要考虑解决如下问题:

  1. 通讯问题 : 主要是通过在客户端和服务器之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享同一个连接。
  2. 寻址问题 : A服务器上的应用怎么告诉底层的RPC框架,如何连接到B服务器(如主机或IP地址)以及特定的端口,方法的名称是什么,这样才能完成调用。比如基于Web服务协议栈的RPC,就要提供一个endpoint URI,或者是从UDDI服务上查找。如果是RMI调用的话,还需要一个RMI Registry来注册服务的地址。
  3. 序列化与反序列化 : 当A服务器上的应用发起远程过程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给B服务器。 同理,B服务器接收参数要将参数反序列化。B服务器应用调用自己的方法处理后返回的结果也要序列化给A服务器,A服务器接收也要经过反序列化的过程。

二、REST

REST即表述性状态传递Representational State Transfer,简称REST),是一种软件架构风格。REST通过HTTP协议定义的通用动词方法(GETPUTDELETEPOST) ,以URI对网络资源进行唯一标识,响应端根据请求端的不同需求,通过无状态通信,对其请求的资源进行表述。

Rest架构的主要原则:

  1. 网络上的所有事物都被抽象为资源
  2. 每个资源都有一个唯一的资源标识符
  3. 同一个资源具有多种表现形式(xml,json等)
  4. 对资源的各种操作不会改变资源标识符
  5. 所有的操作都是无状态的

其中表述性状态,是指(在某个瞬间状态的)资源数据的快照,包括资源数据的内容、表述格式(XML、JSON)等信息。

其中无状态通信,是指服务端(响应端)不保存任何与特定HTTP请求相关的资源,应用状态必须由请求方在请求过程中提供。要求在网络通信过程中,任意一个Web请求必须与其他请求隔离,当请求端提出请求时,请求本身包含了响应端为响应这一请求所需的全部信息。

REST使用HTTP+URI+XML /JSON 的技术来实现其API要求的架构风格:HTTP协议和URI用于统一接口和定位资源,文本、二进制流、XML、JSON等格式用来作为资源的表述。

举例:

在Restful之前的操作: 请求的地址对应具体的业务操作
http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据
http://127.0.0.1/user/save POST 新增用户
http://127.0.0.1/user/update POST 修改用户信息
http://127.0.0.1/user/delete GET/POST 删除用户信息

RESTful用法: 请求类型决定操作
http://127.0.0.1/user/1 GET 根据用户id查询用户数据
http://127.0.0.1/user POST 新增用户
http://127.0.0.1/user PUT 修改用户信息
http://127.0.0.1/user DELETE 删除用户信息

RESTful风格的体现,在你使用了get请求,就是查询;使用post请求,就是新增的请求;使用put请求,就是修改的请求;使用delete请求,就是删除的请求。这样做就完全没有必要对crud做具体的描述。

满足REST约束条件和原则的架构,就被称为是RESTful架构。就像URL都是URI(统一资源标识)的表现形式一样,RESTful是符合REST原则的表现形式。

三、代码

代码:GitHub

3.1 RPC demo

要实现一个简单的 RPC(远程过程调用)框架,你可以遵循以下步骤:

  1. 定义服务接口:首先定义你的服务接口,这个接口定义了客户端可以调用的远程方法。这个接口通常包含服务的所有方法签名,并且必须继承 java.rmi.Remote 接口,并且每个方法都要声明 throws RemoteException。
  2. 实现服务接口:编写实现了服务接口的具体服务类。这个类负责实现服务接口中的方法逻辑,并且承载了客户端请求的处理。
  3. 启动 RMI 注册表:在服务端,启动 RMI 注册表,以便客户端能够找到服务。可以使用java.rmi.registry.LocateRegistry类的静态方法来获取或创建 RMI 注册表。
  4. 注册远程对象:在启动 RMI 注册表后,将实现了服务接口的远程对象绑定到注册表上,以便客户端能够查找和调用。
  5. 编写客户端代码:在客户端编写代码,获取远程对象的引用,并调用远程方法。

以下是一个简单的示例,演示了如何使用 Java RMI 实现一个简单的 RPC 框架。

服务接口:CalculatorService.java

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface CalculatorService extends Remote {
    int add(int a, int b) throws RemoteException;
}

服务实现:CalculatorServiceImpl.java

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class CalculatorServiceImpl extends UnicastRemoteObject implements CalculatorService {

    protected CalculatorServiceImpl() throws RemoteException {
        super();
    }

    @Override
    public int add(int a, int b) throws RemoteException {
        return a + b;
    }
}

服务端:CalculatorServer.java

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class CalculatorServer {

    public static void main(String[] args) {
        try {
            CalculatorService calculatorService = new CalculatorServiceImpl();
            Registry registry = LocateRegistry.createRegistry(8081);
            registry.rebind("CalculatorService", calculatorService);
            System.out.println("服务器运行中...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户端:CalculatorClient.java

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class CalculatorClient {

    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry("localhost", 8081);
            CalculatorService calculatorService = (CalculatorService) registry.lookup("CalculatorService");

            int result = calculatorService.add(10, 5);
            System.out.println("Result of addition: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果:

在这里插入图片描述

3.2 Rest API demo

CalculatorController

@RestController
class CalculatorController {

    @GetMapping("/add")
    public int add(@RequestParam int a, @RequestParam int b) {
        return a + b;
    }
}

CalculatorClient

public class CalculatorClient {
    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();

        String url = "http://localhost:8081/add?a=10&b=5";
        int result = restTemplate.getForObject(url, Integer.class);

        System.out.println("Result of addition: " + result);
    }
}

运行结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/453662.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

人工智能测试开发

随着人工智能在各行各业的广泛应用,学习并掌握AI技术在软件测试中的应用变得至关重要。不仅能使你跟上行业的发展趋势,还能提升你的竞争力。而且,市场对具备AI测试技能的测试工程师的需求正日益增长,这使得掌握这些技能能够帮助你…

MySQL知识点极速入门

准备SQL 创建数据库: 创建一个名为emptest的数据库 create database emptest; use emptest; 创建数据表: 设计一张员工信息表,要求如下: 1. 编号(纯数字) 2. 员工工号 (字符串类型,长度不超…

mac启动skywalking报错

这个命令显示已经成功 但是日志报错了以上内容。 然后去修改。vim .bash_profile 查看全局变量,这个jdk却是有2个。所以这个问题没解决。

考研C语言复习进阶(1)

目录 1. 数据类型介绍 1.1 类型的基本归类: 2. 整形在内存中的存储 2.1 原码、反码、补码 2.2 大小端介绍 3. 浮点型在内存中的存储 ​编辑 1. 数据类型介绍 前面我们已经学习了基本的内置类型: char //字符数据类型 short //短整型 int /…

VTK包围盒,AABB包围盒

1. 概述 包围盒是指能够包含三维图形的长方体,常常用于模型的碰撞检测。包围盒可以分成:轴对齐包围盒(AABB),有向包围盒(OBB)和凸包(Convex Hull) 今天就来实践一下AABB包围盒 2.绘制一个锥体 #include "vtkAutoInit.h" VTK_MODULE_INIT(v…

任务弹窗更新为任务对话框

1.设计初心 在玩家接取任务/交付任务时,界面弹出的UI ,需要与玩家互动,点击“接取”“完成”。等等字样【改动前】频繁的手动点击会中断玩家跑图的流畅性,也降低了任务寻路系统的实际体验。于是现在变成类似FakeObj 对话框的模式…

Filebeat(Beats)详细介绍与使用

1. 什么是 Beats? Beats 是开源数据传送器,将其作为代理安装在服务器上,以将操作数据发送到 Elasticsearch。 Elastic提供Beats用于捕获: 审核数据:Auditbeat 日志文件和日志:Filebeat 云数据:Functio…

网络学习:9个计算机的“网络层”知识点

目录 一、IP 地址 1.1 分类表示法: 1.1.1 分类表示地址的其他说明 1.2 无分类编址 CIDR 二、IP 数据报文格式 Q: IP 报文里有什么?可以不按顺序或者字节来讲一讲 三、 路由概念 3.1 路由表 3.2 路由网络匹配 3.3 ARP 解析 3.4 RARP 逆地址解析…

matplotlib系统学习记录

日期:2024.03.12 内容:将matplotlib的常用方法做一个记录,方便后续查找。 基本使用 # demo01 from matplotlib import pyplot as plt # 设置图片大小,也就是画布大小 fig plt.figure(figsize(20,8),dpi80)#图片大小,清晰度# 准…

代码学习记录18

随想录日记part18 t i m e : time: time: 2024.03.13 主要内容:今天的主要内容是二叉树的第七部分,主要涉及二叉搜索树的最近公共祖先 ;二叉搜索树的最近公共祖先;删除二叉搜索树中的节点 。 23…

HQChart实战教程70-K线图增加成本线

HQChart实战教程70-K线图增加成本线 成本线Y轴子自定义刻度HQChart插件地址步骤1. 创建成本线2. 动态计算盈利值3. 删除成本线交流示例源码成本线 在K线图上,显示一个根当前账户持仓的成本线,可以快速看到盈利状态。方便盯盘。 效果入下图: 第1行是成本价 第2行是盈利点数…

【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件详细说明

欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。…

基于大模型的 Agent 进行任务规划的10种方式

本文首发自博客 基于大模型的 Agent 进行任务规划的10种方式 基于大模型的 Agent 基本组成应该包含规划(planning),工具(Tools),执行(Action),和记忆(Memory)四个方面,上一篇中重点讲了进行长记忆管理的 8…

MFC 添加MFC类方法

1、打开工程目录的"类视图" 2、工程名右键添加"MFC类" 3、填写"类名"并选择“基类”CDialog,对话框ID填写添加好的对话框ID

Vue3 前端生成随机id( 生成 UUID )

效果展示 封装工具(代码展示) 重新创建一个文件**/utils/someTools.js**,并在里面写入如下代码。 function Tools() {}Tools.prototype.guid function () {return xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx.replace(/[xy]/g, function (c) {v…

Junit4入门之什么是单元测试?

干了一年多的后端了,从来没有了解过单元测试。虽然我知道测试不仅仅是测试们的任务,后端也要进行自测来保证自己的代码的可用性,但我一直都只是用postman来实施的,调用调通了即可。虽然我也知道Junit是用于测试的软件,…

汽车屏类产品(五):仪表Cluster常用芯片i.MX117x

前言: 仪表一般就是指方向盘前面那个表盘。做仪表的芯片最主要需要支持显示Display,而仪表的主要排版布局多种多样,但是主旨显示内容不尽相同。 仪表需求: 1、rpm转速表盘 仪表Cluster一般会有转速表盘rpm,单位一般是x1000,大部分汽车仪表范围就是0~8,也就是最高8000…

【Vue3】深入理解Vue3路由器的工作原理to的两种写法

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

大数据 - HBase《一》- Hbase基本概念

目录 1.1. Hbase简介 1.2 Hbase,Hive, Mysql对比 1.3 Hbase数据模型 🥙region(区域) 🥙rowkey(行键) 🥙列族(column family) 🥙列(column Qualifier) 🥙版本(version)-默认按…

Sui与数据平台ZettaBlock达成合作,为其公测提供数据

Sui一向以闪电般的速度、无限水平扩展著称,现已迅速成为DeFi活动的重要场所。近期,数据平台ZettaBlock宣布在其开创性的Web3数据平台发布中,选择Sui作为基础集成合作伙伴之一。在ZettaBlock的开放测试版发布之际,构建者和开发者将…