what is this ?

这是我自己做的一个简易的RPC调用框架,Java实现,基于Spring Framework,通过FASTJSON实现序列化,使用JDK原生的动态代理,使用zk完成服务发现和负载均衡,目前项目正在努力建设中,后期预计在这一套RPC框架,再搓一个MQ的项目。

microRPC系列博客将会记录我从零搭建起一套RPC框架的过程,相关的代码也会同步更新在我的github仓库里面

进度更新

2024.5.17
搭建Netty,client端到server端发request和response测试过了没问题

2024.5.20
构建动态代理框架,client端目前可以通过@RpcCall注解为接口注入动态代理类(通过Spring完成依赖注入)

为什么要做RPC框架

(如果您还不了解什么是微服务和RPC框架可以参考文章什么是微服务 什么是RPC

最近准备搓点项目来丰富自己的简历,参考了一圈后觉得电商类项目和外卖项目过于烂大街,
于是决定做点不一样的,RPC框架相对来说做的人比较少,而且微服务也是几乎每一个互联网公司都在使用的框架,因此做一个自己的RPC框架就显得比较合适,RPC框架中涉及到的不少技术点和细节都可以去深入挖掘和学习,最终成为面试的闪光点。

目前对这个项目的简单规划如下:Java实现,基于netty,做TCP(or http2/3)连接,FASTJSON做序列化,Java原生的动态代理方案,zk做服务发现/lb…

做完这个之后,博主准备在自己搓的RPC框架的基础上,做一个mq项目,当然这都是后话了hhh,但愿能在明年秋招前干完。。

项目前期准备

netty

RPC其实和传统的HTTP调用有一些相似之处,参考RPC和HTTP的区别, 虽然RPC框架为用户屏蔽掉了远程调用的细节,但是用户和远程的服务提供方之间的通信还是通过网络传输完成的,网络通信的常见方式无非就是TCP/UDP通信或者是HTTP连接,那可不可以使用java socket或者是http呢?当然可以,但是性能不够好,传统网络IO编程模型中,需要给每一个连接分配处理线程,造成资源浪费/线程切换时延,因此需要用到IO多路复用的框架 什么是IO多路复用

java中也有NIO框架,但是使用复杂,且有漏洞,而netty则在java NIO的基础上做了一层封装,更加简单易用,关于NETTY详细介绍可以查看 netty ,进阶一点的可以看看netty的架构设计netty:reactor

Netty在高并发的场景下性能更优异,跟Netty相关的问题也是面试官非常喜欢的问题(可以参考上述的文章和其他教程,这里不再赘述)

这个项目中,网络通信使用Netty,即client端发起rpc调用,代理类获取调用方法名称参数等信息,构造request,调用Netty客户端,完成发送

动态代理

关于代理模式、静态代理和动态代理等知识可以参考java代理简介

在Rpc框架中,服务的逻辑是实现在server端的,例如,server端实现了一个sum服务

1
2
3
4
5
6
7
8
9
10
public interface SumService {
int sum(int a, int b);
}

public class SumServiceImpl implements SumService {
@override
int sum(int a, int b) {
return a + b;
}
}

而client端实际上只会定义一个相同的接口SumService,然后就直接调用sum方法

1
2
3
4
5
6
7
public interface SumService {
int sum(int a, int b);
}

@RpcCall
SumService sumService;
sumService.sum(1, 2);

客户端虽然没有实现Sumservice的实现类,但是Rpc框架通过@RpcCall注解,找到了sumService,为其生成动态代理类,在代理类中完成参数组装和发送到server端的逻辑

Spring Framework

这个项目是基于Spring Framework开发的,客户端的每一个Rpc调用类,都被Spring框架识别为Bean,并且在初始化阶段为Rpc接口注入代理类

因此,需要了解的前置知识有Spring的基本概念Spring Bean的生命周期BeanPostProcessor简介(后续通过这个processor完成代理类的注入)

服务发现

挖个坑,等做了这个再仔细写

他山之石

主要参照javaguide哥的guide-rpc-framework和阿里的开源RPC项目dubbo

项目预期进展

完整的RPC框架需要有服务发现功能,即server启动时把自己的服务注册到zk等分布式内存数据库上,然后client在调用的时候,先去zk中拿到server的地址,然后再序列化,发送到server上,等待server的执行结果,最后返回(当然这个过程是由动态代理生成的代理类完成)

这个过程有点繁琐,于是我准备先整个简单的,我不要zk这种注册中心,直接在client端写死地址,把序列化后的数据传给server端执行再返回完事儿,这样就只需要先写好动态代理和序列化、以及server端使用反射去拿到对应方法的逻辑就好了。

我把这个简化版的RPC框架称为p2pRPC,因为服务调用过程是client和server点对点通信完成的

项目地址&进度

项目开源在我的github上,目前只是按照前面所述,写p2pRPC分支,预计两周把这个写完,然后一个月写完服务发现,两个月内搞定整个项目,干干干!!

暂时就酱,后续写了再更新。。