【Java手写RPC框架系列-1】—— 基础知识准备:RPC+Netty

news/2024/11/17 9:06:22/文章来源:https://www.cnblogs.com/P201821440041/p/18357932

代码随想录知识星球介绍
https://articles.zsxq.com/id_m76jd72243bi.html
基于Netty手写实现RPC
https://www.cnblogs.com/mic112/p/15565795.html

项目背景与介绍

  • RPC:
    • 远程过程调用协议:客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样;
    • 要点
      • RPC是协议
      • 网络协议或者网络IO模型对其透明;RPC客户端认为自己在调用本地对象;不关心传输层协议
      • 信息格式透明:参数以某种信息格式传递给网络上另一台计算机,信息格式是怎么构成的,调用者不关心
      • 跨语言能力:不清楚远程服务器的应用程序是使用什么语言运行;对调用方来说,无论服务器方使用什么语言,本次调用都应该成功;返回值也应该按照调用方程序语言所能理解的形式进行描述。
  • 常用RPC技术或框架
    • 应用级
    • 远程通信协议:RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)
    • 通信框架:MINA和Netty
  • 目的:仿照市场主流的RPC框架设计思想,使用java手动实现一个高性能、高可用性的RPC框架

业内主流RPC

  1. Thrift:thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。
  2. Dubbo:Dubbo是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。 Dubbo是阿里巴巴内部的SOA服务化治理方案的核心框架,Dubbo自2011年开源后,已被许多非阿里系公司使用。

基础需求

  • 场景:
    服务端B:有一个用户表
    1.UserService 里有一个功能: getUserByUserId(Integer id)
    2.UserServiceImpl 实现了UserService接口和方法
    客户端A
    • 调用getUserByUserId方法, 内部传一个Id给服务端,服务端查询到User对象返回给客户端
  • 实现过程:
    • 客户端A

      • 调用getUserByUserId方法时,内部将调用信息处理后发送给服务端B,告诉B我要获取User
      • 外部调用方法,内部进行其它的处理——这种场景我们可以使用动态代理的方式,改写原本方法的处理逻辑。比如,当我们正常调用getUserByUserId方法,代码逻辑是去数据库中找user,但是在当前远程调用的场景下肯定不能走这样的逻辑;我们通过动态代理的方式,绕过【去数据库查询】这原始的逻辑,改成封装信息发送到B中请求调用服务
    • 服务器B:

      • 监听A请求,接收A的调用信息,并根据信息得到A想调用的服务与方法
      • 根据信息找到对应的服务,进行调用后将结果发送回给A
    • A和B之间通信

      • Java的Socket网络编程通信
      • 为了方便A,B直接对信息进行处理,将请求信息和返回信息封装成统一的消息格式

网络IO通信

  • 传统BIO模式/同步阻塞IO:客户端向服务端发起一个数据读取请求,客户端在收到服务端返回数据之前,一直处于阻塞状态,直到服务端返回数据后完成本次会话。
    • 一个连接一个线程
    • 客户端有连接请求时,服务器端启动一个线程进行处理
    • 适合场景:HTTP请求
    • 阻塞点:
      • 服务端接收客户端连接时的阻塞;
      • 客户端和服务端IO通信时,数据未就绪情况下阻塞;
  • NIO/非阻塞IO:客户端向服务端发起请求时,如果服务端的数据未就绪的情况下, 客户端请求不会被阻塞,而是直接返回。
    • 客户端只能通过轮询的方式来获得请求结果
    • NIO仍然有一个弊端,就是轮询过程中会有很多空轮询,而这个轮询会存在大量的系统调用(发起内核指令从网卡缓冲区中加载数据,用户空间到内核空间的切换),随着连接数量的增加,会导致性能问题。
  • 多路复用机制
    • 单个进程监视多个文件描述符(fd)
    • 一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作
    • 常见多路复用方式:
      • 【select】:进程可以通过把一个或者多个fd传递给select系统调用,进程会阻塞在select操作上,这样select可以帮我们检测多个fd是否处于就绪状态,这个模式有两个缺点
        • 当前进程需要线性轮询所有的fd,也就是监听的fd越多,性能开销越大
        • 在单个进程中能打开的fd是有限制的,默认是1024
      • 【poll】:
      • 【epoll】:inux还提供了epoll的系统调用,epoll是基于事件驱动方式来代替顺序扫描,因此性能相对来说更高
        • 当被监听的fd中,有fd就绪时,会告知当前进程具体哪一个fd就绪,那么当前进程只需要去从指定的fd上读取数据即可,另外,epoll所能支持的fd上线是操作系统的最大文件句柄,这个数字要远远大于1024

什么是fd:在linux中,内核把所有的外部设备都当成是一个文件来操作,对一个文件的读写会调用内核提供的系统命令,返回一个fd(文件描述符)。而对于一个socket的读写也会有相应的文件描述符,成为socketfd。

【使用NIO的api来完成多路复用机制,实现伪异步IO。】
【Netty的I/O模型是基于非阻塞IO实现的,底层依赖的是JDK NIO框架的多路复用器Selector来实现。一个多路复用器Selector可以同时轮询多个Channel,采用epoll模式后,只需要一个线程负责Selector的轮询,就可以接入成千上万个客户端连接。】



  • 异步IO
    • 数据就绪后,客户端不需要发送内核指令从内核空间读取数据,而是系统会异步把这个数据直接拷贝到用户空间,应用程序只需要直接使用该数据即可;

Netty —— 高性能通信框架

Netty提供了上述三种Reactor模型的支持,我们可以通过Netty封装好的API来快速完成不同Reactor模型的开发,这也是为什么大家都选择Netty的原因之一,除此之外,Netty相比于NIO原生API,它有以下特点:

  • 提供了高效的I/O模型、线程模型和时间处理机制
  • 提供了非常简单易用的API
  • 对数据协议和序列化提供了很好的支持
  • 稳定性,Netty修复了JDK NIO较多的问题
  • 可扩展性在同类型的框架中都是做的非常好的
  • 性能层面的优化
    • 对象池复用
    • 零拷贝技术

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

非线性规划的经典例题--选址问题

本章会介绍如何利用非线性规划解决选址问题,这个问题是文章线性规划在数学建模中的两道例题中第二道投料问题的第二小题,本章为基于这道题的基础上进行介绍,建议读者返回去看一看 目录一、问题提出二、问题分析三、模型建立四、代码实现1.输入目标函数2.输入线性约束 一、问…

了解10X文库组成

转的文章 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/LittleComputerRobot/article/details/137207083R1: 26 表示10X barcode 的 16bp碱基 + 10bp UMI; i7: 8表示 8bp 样本index序列 Read…

Java数组07:稀疏数组

1. 线性结构线性结构是最常用的数据结构,其特点是数据元素之间存在一对一的线性关系。 线性结构有两种不同存储结构,即顺序存储结构和链式存储结构。 顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的,即在内存中是连续的,例如数组。 链式存储的线性表称为链表,链表…

【Django开发】django美多商城项目完整开发4.0第2篇:项目准备【附代码文档】

本教程的知识点为:美多商城 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片验证码 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送短信 判断帐号是否存在 1. 判断用户名是否存在 后端…

IntelliJ IDEA 单元测试插件 TestMe

IntelliJ IDEA 添加单元测试插件 TestMe

Redis 使用场景

Redis 使用场景前三种使用广泛,另加队列用

Datawhale X 魔搭 AI夏令营 AIGC方向 Task2

代码逐行解析 先记录一下baseline代码通义千问生成的逐行解析: # 安装 Data-Juicer 和 DiffSynth-Studio !pip install simple-aesthetics-predictor # 安装simple-aesthetics-predictor !pip install -v -e data-juicer # 安装data-juicer !pip uninstall pytorch-lightning …

[Paper Reading] Multiple View Geometry Transformers for 3D Human Pose Estimation

Multiple View Geometry Transformers for 3D Human Pose Estimation link 时间:CVPR2024 机构:University of Toronto && Southeast University && Microsoft Research Asia TL;DR 提出一种基于Transformer端到端3D Human Pose Estimation方法MVGFormer,核…

MySQL8.0 Clone Plugin 实现解析浅析

MySQL8.0 Clone Plugin 实现解析浅析 从8.0.17版本开始官方实现了clone的功能,允许用户通过简单的SQL命令把远端/本地的数据库实例拷贝到其他实例后快速拉起一个新的实例。 该功能由一些列的WL组成 :Clone local replica(WL#9209) : 实现了数据本地Clone。 Clone remote repli…

USB协议详解第8讲(USB描述符-字符串和语言ID描述符)

1.字符串描述符相关概念 字符串描述符:首先,字符串描述符就是用字符串描述一个设备的一些属性,毕竟人能看懂的是字符,而不是十六进制,描述的属性包括设备厂商名字、产品名字、产品序列号、各个配置名字、各个接口名字,还有就是由我们用户自己定义的字符串,说白了就是起名…

【Azure Developer】使用Python SDK去Azure Container Instance服务的Execute命令的疑问解释

Azure 容器实例(Azure Container Instances,简称 ACI)是一个无服务器容器解决方案,允许用户在 Azure 云环境中运行 Docker 容器,而无需设置虚拟机、集群或编排器。ACI 适用于任何可以在隔离容器中操作的场景,包括事件驱动的应用程序、从容器开发管道快速部署、数据处理和…

DCDC电路设计之FB引脚布线

该随笔从与非网上搬运,原文: 案例讲解,DCDC电源反馈路径的布线规则 下面为正文内容: 在本文中,将对用来将输出信号反馈给电源ic的FB引脚的布线进行说明。 反馈路径的布线 反馈信号的布线在信号布线过程中也需要特别注意。反馈信号如Figure 7-a左侧的电路图所示,输出电压经…