性能基础之常见RPC框架浅析

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
云服务器ECS,u1 2核4GB 1个月
简介: 【4月更文挑战第23天】性能基础之常见RPC框架浅析

2000元阿里云代金券免费领取,2核4G云服务器仅664元/3年,新老用户都有优惠,立即抢购>>>


阿里云采购季(云主机223元/3年)活动入口:请点击进入>>>,


阿里云学生服务器(9.5元/月)购买入口:请点击进入>>>,

引言

在性能基础之浅谈常见接口性能压测一文中我们有简单介绍常见的 RPC 接口,本文将单篇详细介绍 RPC 协议。

什么是RPC?

RPCRemote Procedure Call)—远程过程调用 ,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC 协议假定某些传输协议的存在,如 TCP 或 UDP,为通信程序之间携带信息数据。在 OSI 网络通信模型中,RPC 跨越了传输层和应用层。

其实简单点的说,就是像调用本地的类的方法样来调用服务器端的方法实现。比如两个不同的服务 A,B 部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP 请求当然可以,但是可能会比较慢而且一些优化做的并不好。 RPC 的出现就是为了解决这个问题。总之,RPC 使得开发分布式程序就像开发本地程序一样简单。

RPC原理是什么?

RPC 采用客户端(服务调用方)/服务器端(服务提供方)模式, 都运行在自己的 JVM 中。客户端只需要引入要使用的接口,接口的实现和运行都在服务器端。RPC 主要依赖的技术包括序列化、反序列化和数据传输协议,这是一种定义与实现相分离的设计。

image.png

同时需要对 RMI(Remote Method Invoke,远程方法调用)中的 stub (桩)和skeleton (骨架)的概念有一点了解。RMI 的代理模式是通过代理对象将方法传递给实际对象的。stub 驻留客户端,承担着代理远程对象实现者的角色。skeleton 类帮助远程对象与 stub 连接进行通信。

image.png

  1. 服务调用方(client)调用以本地调用方式调用服务;
  2. client stub 接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  3. client stub 找到服务地址,并将消息发送到服务端;
  4. server stub 收到消息后进行解码;
  5. server stub 根据解码结果调用本地的服务;
  6. 本地服务执行并将结果返回给 server stub
  7. server stub 将返回结果打包成消息并发送至调用方;
  8. client stub 接收到消息,并进行解码;
  9. 服务调用方得到最终结果。

主要组成元素:

image.png

实体对象和业务接口由客户端和服务端公用。
接口实现是由服务端对定义好的业务接口进行功能实现,并将接口实例注册服务中提供给客户端调用。

常见RPC框架

目前 Java 使用比较多的 RPC 方案主要有RMI(JDK自带)、Hessian、Dubbo、Hprose、Thrift 以及 HTTP 等。

注意: RPC 主要指内部服务之间的调用,RESTful 也可以用于内部服务之间的调用,但其主要用途还在于外部系统提供服务,因此没有将其包含在本知识点内。

RMI

JDK自带的RPC

Java RMI (Remote Method Invocation)- 远程方法调用,能够让客户端像使用本地调用一样调用服务端 Java 虚拟机中的对象方法。RMI 是面向对象语言领域对 RPC (Remote Procedure Call)的完善,用户无需依靠 IDL 的帮助来完成分布式调用,而是通过依赖接口这种更简单自然的方式。

Java RMI 工作原理

一个典型的 RMI 调用如下图所示:
image.png

  1. 服务端向 RMI 注册服务绑定自己的地址
  2. 客户端通过 RMI 注册服务获取目标地址,
    1. 客户端调用本地的 Stub 对象上的方法,和调用本地对象上的方法一致,
    2. 本地存根对象将调用信息打包,通过网络发送到服务端,
    3. 服务端的 Skeleton 对象收到网络请求之后,将调用信息解包,
    4. 然后找到真正的服务对象发起调用,并将返回结果打包通过网络发送回客户端。

Java RMI 基本概念

Java RMI 是 Java 领域创建分布式应用的技术基石。后续的 EJB 技术,以及现代的分布式服务框架,其中的基本理念依旧是 Java RMI 的延续。在 RMI 调用中,有以下几个核心的概念:

  1. 通过接口进行远程调用
  2. 通过客户端的 Stub 对象和服务端的 Skeleton 对象的帮助将远程调用伪装成本地调用
  3. 通过 RMI 注册服务完成服务的注册和发现

对于第一点,客户端需要依赖接口,而服务端需要提供该接口的实现。
对于第二点,在 J2SE 1.5版本之前需要通过 rmic 预先编译好客户端的 Stub 对象和服务端的 Skeleton 对象。在之后的版本中,不再需要事先生成 Stub 和 Skeleton 对象。

下面通过示例代码简单的展示 RMI 中的服务注册和发现

服务端的服务注册

Hello obj = new HelloImpl(); // #1
Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); // #2
Registry registry = LocateRegistry.createRegistry(1099); // #3
registry.rebind("Hello", stub); // #4

说明:

  1. 初始化服务对象实例,
  2. 通过 UnicastRemoteObject.exportObject 生成可以与服务端通讯的 Stub 对象,
  3. 创建一个本地的 RMI 注册服务,监听端口为 1099。该注册服务运行在服务端,也可以单独启动一个注册服务的进程,
  4. 将 Stub 对象绑定到注册服务上,这样,客户端可以通过 Hello 这个名字查找到该远程对象。

    客户端的服务发现

    Registry registry = LocateRegistry.getRegistry(); // #1
    Hello stub = (Hello) registry.lookup("Hello"); // #2
    String response = stub.sayHello(); // #3
    
    说明:
  5. 获取注册服务实例,在本例中,由于没有传入任何参数,假定要获取的注册服务实例部署在本机,并监听在 1099 端口上,
  6. 从注册服务中查找服务名为 Hello 的远程对象,
  7. 通过获取的 Stub 对象发起一次 RMI 调用并获得结果。

理解 RMI 的工作原理和基本概念,对掌握现代分布式服务框架很有帮助,建议进一步的阅读 RMI 官方教材。

Dubbo

Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。
image.png

节点说明:

  • Provider:暴露服务的服务提供方
  • Consumer:调用远程服务的服务消费方
  • Registry:服务注册与发现的注册中心
  • Monitor:统计服务调用次数和服务调用时间的监控中心
  • Container:服务运行容器

Hessian

Hessian是一个轻量级的 remotingonhttp 工具,使用简单的方法提供了RMI的功能。 相比 WebService,Hessian 更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。
image.png

Thrift

Apache Thrift 是 Facebook 开源的跨语言的 RPC 通信框架,目前已经捐献给 Apache 基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于 thrift 研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。

image.png

Hprose

国人开发的一个远程方法调用的开源框架。它是一个先进的轻量级的跨语言跨平台面向对象的高性能远程动态通讯中间件。

HTTP

常见于 WEB 应用,基于 HTTP(s) 协议传输文本。当一个 URL发送请求时,服务端 doGet 或者 doPost 方法会被调用,获取相应的参数。压测HTTP接口时,只需要通过定位URL接口并传参,相对比较简单。

image.png

如何进行选择?

  • 是否允许代码侵入: 即需要依赖相应的代码生成器生成代码,比如 Thrift。
  • 是否需要长连接获取高性能: 如果对于性能需求较高的 haul,那么可以果断选择基于 TCP 的 Thrift、Dubbo。
  • 是否需要跨越网段、跨越防火墙: 这种情况一般选择基于 HTTP 协议的Hessian 和 Thrift 的 HTTP Transport。
  • 此外,Google 推出的基于 HTTP2.0 的 gRPC 框架也开始得到应用,其序列化协议基于 Protobuf,网络框架使用的是 Netty4 ,但是其需要生成代码,可扩展性比较差。

小结

现代 RPC 的本质其实就是在网络上传输数据包,而这个数据包的特点是 Header+Body。Header即协议头,分为定长或者变长,这个取决于协议的设计者。例如 dubbo 协议就是定长的。而有些协议是变长的。Body 就是消息体,其实就是对象序列化的过程,把序列化好的数据放入 Body里面。现在流行的序列化方案有 Hessian,java-built-in,JSON,MsgPack,Protobuf等。底层框架一般使用 NIO/Netty 架构,因为是异步通信,需要支持高性能、高并发。

参加文献:

目录
相关文章
|
JSON 网络协议 Dubbo
RPC框架(技术总结)
RPC框架(技术总结)
RPC框架(技术总结)
|
4月前
|
消息中间件 Dubbo Java
Simple RPC - 01 框架原理及总体架构初探
Simple RPC - 01 框架原理及总体架构初探
51 0
|
10月前
|
XML JSON 负载均衡
探秘Linux网络设计:Reactor模型与高效http静态服务器构建
本文将深入探讨Linux网络设计中的Reactor模型,并展示如何利用该模型构建高效的http静态服务器。在现代互联网环境中,快速响应和高吞吐量对于提供卓越用户体验至关重要。通过理解Reactor模型的基本概念和工作原理,我们将揭示它在构建高并发应用中的关键作用。本文还将详细介绍如何利用Reactor模型优化网络通信,实现快速的http请求处理和静态资源传输。通过实践经验的分享,包括事件驱动编程、多线程和多进程处理以及负载均衡等技巧,读者将获得构建高效http静态服务器的实际指导和启示。
184 0
探秘Linux网络设计:Reactor模型与高效http静态服务器构建
|
数据采集 网络协议 算法
RPC框架整体架构
RPC就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证在服务提供方能正确地还原出语义,最终实现像调用本地一样地调用远程的目的。
207 0
|
Java API 开发者
motan扩展机制
motan第二篇,想写motan的rpc调用过程的,但项目中需要对motan进行扩展,所以本来就先记录下
152 0
|
XML JSON 运维
RPC框架:从原理到选型,一文带你搞懂RPC(二)
RPC系列的文章是我去年写的,当时写的比较散,现在重新进行整理。对于想学习RPC框架的同学,通过这篇文章,让你知其然并知其所以然,便于以后技术选型
410 0
RPC框架:从原理到选型,一文带你搞懂RPC(二)
|
Dubbo 网络协议 JavaScript
RPC框架:从原理到选型,一文带你搞懂RPC(一)
RPC系列的文章是我去年写的,当时写的比较散,现在重新进行整理。对于想学习RPC框架的同学,通过这篇文章,让你知其然并知其所以然,便于以后技术选型
964 0
RPC框架:从原理到选型,一文带你搞懂RPC(一)
|
负载均衡 Dubbo Java
RPC框架:从原理到选型,一文带你搞懂RPC(三)
RPC系列的文章是我去年写的,当时写的比较散,现在重新进行整理。对于想学习RPC框架的同学,通过这篇文章,让你知其然并知其所以然,便于以后技术选型
364 0
RPC框架:从原理到选型,一文带你搞懂RPC(三)
|
JSON 负载均衡 算法
轻量级RPC框架(0 - 项目概述)
轻量级RPC框架(0 - 项目概述)
轻量级RPC框架(0 - 项目概述)
|
XML NoSQL 中间件
手写RPC框架第三章《RPC中间件》
1、注册中心,生产者在启动的时候需要将本地接口发布到注册中心,我们这里采用redis作为注册中心,随机取数模拟权重。 2、客户端在启动的时候,连接到注册中心,也就是我们的redis。连接成功后将配置的生产者方法发布到注册中心{接口+别名}。 3、服务端配置生产者的信息后,在加载xml时候由中间件生成动态代理类,当发生发放调用时实际则调用了我们代理类的方法,代理里会通过netty的futuer通信方式进行数据交互。
436 1
http://www.vxiaotou.com