Add files via upload

This commit is contained in:
xiaobaozi-web 2024-12-06 20:29:51 +08:00 committed by GitHub
parent ab0870519c
commit e9268d2141
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

449
README.md
View File

@ -1,222 +1,227 @@
# RPC-Java
[【代码随想录知识星球】](https://www.programmercarl.com/other/kstar.html)项目分享-手撕RPC框架[项目专栏](https://t.zsxq.com/0CVPn) 有本项目的详细文档
* [第一章:项目背景、项目收获、简历写法、项目架构和流程图](https://t.zsxq.com/RtJmQ)
* [第二章版本一实现一个基本的rpc调用](https://t.zsxq.com/QImhy)
* [第三章版本二netty自定义编码器解码器和序列化器创建缓存](https://t.zsxq.com/osLak)
* [第四章(版本三):负载均衡、超时重试 &白名单](https://t.zsxq.com/zVqPE)
* [第五章(版本四):服务-限流、熔断](https://t.zsxq.com/Oj1gG0)
* [第六章:项目常见问题以及如何回答(网络传输层面,注册中心层面,算法层面,各种场景题](https://t.zsxq.com/xOAAq)
## 启动流程
1.先安装并开启zookeeper
安装参考:
[【Zookeeper】Windows下安装Zookeeper图文记录详细步骤手把手包安装成功_windows安装zk-CSDN博客](https://blog.csdn.net/tttzzzqqq2018/article/details/132093374?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172149339116800211548359%2522%252C%2522scm%2522%253A%252220140713.130102334)
2.运行Server包下的TestServer,再运行Client包下的TestClient
# RPC概念
### 概念
1. RPCRemote Procedure Call Protocol 远程过程调用协议。
2. RPC是一种通过网络从远程计算机程序上请求服务不需要了解底层网络技术的协议。
3. RPC主要作用就是不同的服务间方法调用就像本地调用一样便捷。
### 常用RPC技术或框架
应用级的服务框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。
远程通信协议RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
通信框架MINA 和 Netty
### 为什么要有RPC
1. 服务化:微服务化,跨平台的服务之间远程调用;
2. 分布式系统架构:分布式服务跨机器进行远程调用;
3. 服务可重用:开发一个公共能力服务,供多个服务远程调用。
4. 系统间交互调用两台服务器A、B服务器A上的应用a需要调用服务器B上的应用b提供的方法而应用a和应用b不在一个内存空间不能直接调用此时需要通过网络传输来表达需要调用的语义及传输调用的数据。
#### 使用场景
1. `大型网站`:内部涉及多个子系统,服务、接口较多。
2. `注册发现机制`如Nacos、Dubbo等一般都有注册中心服务有多个实例调用方调用的哪个实例无感知。
3. `安全性`:不暴露资源
4. `服务化治理`:微服务架构、分布式架构。
### 架构图
![](README.assets/655c04a02b08474e985ff4bf8a561d12.png)
### 核心功能概念
核心功能实现主要分为**服务寻址**、**序列化和反序列化**、**网络传输功能**。
#### 服务寻址功能
**Call ID映射**
本地:在本地方法调用中,函数体是直接通过函数指针来指定的,但是在远程调用中,由于两个进程的地址空间完全不一样,函数指针不起作用。
远程RPC中所有函数或方法都有自己的一个ID在所有进程中都唯一。客户端在做远程过程调用时必须附上这个ID即客户端会查一下表找出相应的Call ID然后传给服务端服务端也会查表来确定客户端需要调用的函数然后执行相应函数的代码。
Call ID映射表一般是一个哈希表。
#### 序列化和反序列化功能
**概述:**
- 序列化:将消息对象转换为二进制流。
- 反序列化:将二进制流转换为消息对象。
**必要性**
远程调用涉及到数据的传输,在本地调用中,只需要将数据压入栈中,然后让函数去栈中读取即可。
但远程的数据传输,由于客户端和服务端不在同一个服务器上,涉及不同的进程,不能通过内存传递参数,此时就需要将客户端先将请求参数转成字节流(编码),传递给服务端,服务端再将字节流转为自己可读取格式(解码),这就是序列化和反序列化的过程。反之,服务端返回值也逆向经历序列化和反序列化到客户端。
**序列化的优势:**
将消息对象转为二进制字节流,便于网络传输。
可跨平台、跨语言。如Python编写的客户端请求序列化参数传输到Java编写的服务端进行反序列化。
#### 网络传输功能
**作用**
- 客户端将Call ID和序列化后的参数字节流传输给服务端。
- 服务端将序列化后的调用结果回传给客户端。
**协议**
主要有TCP、UDP、HTTP协议。
**基于TCP协议**
客户端和服务端建立Socket连接。
客户端通过Socket将需要调用的接口名称、方法名称及参数序列化后传递给服务端。
服务端反序列化后再利用反射调用对应的方法,将结果返回给客户端。
**基于HTTP协议**
客户端向服务端发送请求如GET、POST、PUT、DELETE等请求。
服务端根据不同的请求参数和请求URL进行方法调用返回JSON或者XML数据结果。
**TCP和HTTP对比**
- 基于TCP协议实现的RPC调用由于是底层协议栈更佳灵活的对协议字段进行定制可减少网络开销提高性能实现更大的吞吐量和并发数。但**,底层复杂,实现代价高**。
- 基于HTTP协议实现的RPC调用已封装实现序列化但HTTP属于应用层协议HTTP传输**所占用的字节数比TCP更高传输效率对比TCP较低**。
# 版本一
**part1**
- 实现基本的rpc调用
- 客户端动态代理
- 定义统一的request和response
**part2**
- 引入netty框架进行信息传输
- 自定义消息格式
**part3**
- 引入zookeeper作为注册中心
![1720376325450](README.assets/1720376325450.png)
# 版本二
**part1**
- netty自定义编码器解码器和序列化器
**part2**
- 在客户端建立本地服务缓存
- 实现本地缓存的动态更新
![1720376518663](README.assets/1720376518663.png)
# 版本三
**part1**
- 实现客户端的负载均衡
**part2**
- 实现客户端的容错:失败重传
- 服务白名单
![1720376674829](README.assets/1720376674829.png)
# 版本四
**part1**
- 服务限流,降级的实现
- 熔断器的实现
![1720376759165](README.assets/1720376759165.png)
# TodoList
- [ ] 补充其它序列化方式如ProtoBufHessian
- [ ] 集成Spring
- [ ] 主动下线失败次数过多的节点
- [ ] 探测离线节点的状态,对恢复正常的节点重新上线
- [ ] 实现自适应的负载均衡器
# RPC-Java
[【代码随想录知识星球】](https://www.programmercarl.com/other/kstar.html)项目分享-手撕RPC框架[项目专栏](https://t.zsxq.com/0CVPn) 有本项目的详细文档
* [第一章:项目背景、项目收获、简历写法、项目架构和流程图](https://t.zsxq.com/RtJmQ)
* [第二章版本一实现一个基本的rpc调用](https://t.zsxq.com/QImhy)
* [第三章版本二netty自定义编码器解码器和序列化器创建缓存](https://t.zsxq.com/osLak)
* [第四章(版本三):负载均衡、超时重试 &白名单](https://t.zsxq.com/zVqPE)
* [第五章(版本四):服务-限流、熔断](https://t.zsxq.com/Oj1gG0)
* [第六章:项目常见问题以及如何回答(网络传输层面,注册中心层面,算法层面,各种场景题](https://t.zsxq.com/xOAAq)
## 启动流程
1.先安装并开启zookeeper
安装参考:
[【Zookeeper】Windows下安装Zookeeper图文记录详细步骤手把手包安装成功_windows安装zk-CSDN博客](https://blog.csdn.net/tttzzzqqq2018/article/details/132093374?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172149339116800211548359%2522%252C%2522scm%2522%253A%252220140713.130102334)
2.运行Server包下的TestServer,再运行Client包下的TestClient
# RPC概念
### 概念
1. RPCRemote Procedure Call Protocol 远程过程调用协议。
2. RPC是一种通过网络从远程计算机程序上请求服务不需要了解底层网络技术的协议。
3. RPC主要作用就是不同的服务间方法调用就像本地调用一样便捷。
### 常用RPC技术或框架
应用级的服务框架:阿里的 Dubbo/Dubbox、Google gRPC、Spring Boot/Spring Cloud。
远程通信协议RMI、Socket、SOAP(HTTP XML)、REST(HTTP JSON)。
通信框架MINA 和 Netty
### 为什么要有RPC
1. 服务化:微服务化,跨平台的服务之间远程调用;
2. 分布式系统架构:分布式服务跨机器进行远程调用;
3. 服务可重用:开发一个公共能力服务,供多个服务远程调用。
4. 系统间交互调用两台服务器A、B服务器A上的应用a需要调用服务器B上的应用b提供的方法而应用a和应用b不在一个内存空间不能直接调用此时需要通过网络传输来表达需要调用的语义及传输调用的数据。
#### 使用场景
1. `大型网站`:内部涉及多个子系统,服务、接口较多。
2. `注册发现机制`如Nacos、Dubbo等一般都有注册中心服务有多个实例调用方调用的哪个实例无感知。
3. `安全性`:不暴露资源
4. `服务化治理`:微服务架构、分布式架构。
### 架构图
![](README.assets/655c04a02b08474e985ff4bf8a561d12.png)
### 核心功能概念
核心功能实现主要分为**服务寻址**、**序列化和反序列化**、**网络传输功能**。
#### 服务寻址功能
**Call ID映射**
本地:在本地方法调用中,函数体是直接通过函数指针来指定的,但是在远程调用中,由于两个进程的地址空间完全不一样,函数指针不起作用。
远程RPC中所有函数或方法都有自己的一个ID在所有进程中都唯一。客户端在做远程过程调用时必须附上这个ID即客户端会查一下表找出相应的Call ID然后传给服务端服务端也会查表来确定客户端需要调用的函数然后执行相应函数的代码。
Call ID映射表一般是一个哈希表。
#### 序列化和反序列化功能
**概述:**
- 序列化:将消息对象转换为二进制流。
- 反序列化:将二进制流转换为消息对象。
**必要性**
远程调用涉及到数据的传输,在本地调用中,只需要将数据压入栈中,然后让函数去栈中读取即可。
但远程的数据传输,由于客户端和服务端不在同一个服务器上,涉及不同的进程,不能通过内存传递参数,此时就需要将客户端先将请求参数转成字节流(编码),传递给服务端,服务端再将字节流转为自己可读取格式(解码),这就是序列化和反序列化的过程。反之,服务端返回值也逆向经历序列化和反序列化到客户端。
**序列化的优势:**
将消息对象转为二进制字节流,便于网络传输。
可跨平台、跨语言。如Python编写的客户端请求序列化参数传输到Java编写的服务端进行反序列化。
#### 网络传输功能
**作用**
- 客户端将Call ID和序列化后的参数字节流传输给服务端。
- 服务端将序列化后的调用结果回传给客户端。
**协议**
主要有TCP、UDP、HTTP协议。
**基于TCP协议**
客户端和服务端建立Socket连接。
客户端通过Socket将需要调用的接口名称、方法名称及参数序列化后传递给服务端。
服务端反序列化后再利用反射调用对应的方法,将结果返回给客户端。
**基于HTTP协议**
客户端向服务端发送请求如GET、POST、PUT、DELETE等请求。
服务端根据不同的请求参数和请求URL进行方法调用返回JSON或者XML数据结果。
**TCP和HTTP对比**
- 基于TCP协议实现的RPC调用由于是底层协议栈更佳灵活的对协议字段进行定制可减少网络开销提高性能实现更大的吞吐量和并发数。但**,底层复杂,实现代价高**。
- 基于HTTP协议实现的RPC调用已封装实现序列化但HTTP属于应用层协议HTTP传输**所占用的字节数比TCP更高传输效率对比TCP较低**。
# 版本一
**part1**
- 实现基本的rpc调用
- 客户端动态代理
- 定义统一的request和response
**part2**
- 引入netty框架进行信息传输
- 自定义消息格式
**part3**
- 引入zookeeper作为注册中心
![1720376325450](README.assets/1720376325450.png)
# 版本二
**part1**
- netty自定义编码器解码器和序列化器
**part2**
- 在客户端建立本地服务缓存
- 实现本地缓存的动态更新
![1720376518663](README.assets/1720376518663.png)
# 版本三
**part1**
- 实现客户端的负载均衡
**part2**
- 实现客户端的容错:失败重传
- 服务白名单
![1720376674829](README.assets/1720376674829.png)
# 版本四
**part1**
- 服务限流,降级的实现
- 熔断器的实现
![1720376759165](README.assets/1720376759165.png)
# 版本五
- 添加Hessian、protostuff、kryo等序列化方式
- 优化了服务端的关闭
- 配置顶
- SPI机制
![](assets/image.png)
# TodoList
- [ ] 集成Spring
- [ ] 主动下线失败次数过多的节点
- [ ] 探测离线节点的状态,对恢复正常的节点重新上线
- [ ] 实现自适应的负载均衡器