# RPC-FromZero **Repository Path**: kuangty/rpc-from-zero ## Basic Information - **Project Name**: RPC-FromZero - **Description**: 从0开始构造一个RPC框架 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-06 - **Last Updated**: 2021-10-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🏆RPC-KTY ## 🥥简介 - RPC-KTY一款基于 Netty + Kyro / Protostuff + Zookeeper 实现的 RPC 框架。那么何为RPC框架呢?RPC(Remote Procedure Call)即远程过程调用,通过名字我们就能看出 RPC 关注的是远程调用而非本地调用。通过 RPC 可以帮助我们调用远程计算机上某个服务的方法,这个过程就像调用本地方法一样简单。并且我们不需要了解底层网络编程的具体细节😄😄😄 ## 💻技术栈 - 🎥**Java基础**: - 动态代理机制(态代理 + JDK / CGLIB / Javassit 动态代理) - Java I/O 系统 - Java 并发/多线程 - Java 网络编程(Socket 编程) - Java 注解 - Java 反射 - 序列化机制以及序列化框架(Kryo / Protostuff )的基本使用 - 📙**Netty**:使 NIO 编程更加容易,屏蔽了 Java 底层的 NIO 细节 - 📑**Zookeeper**:提供服务注册与发现功能,开发分布式系统的必备选择,具备天生的集群能力 - 🗳**Spring Framework(Spring)**:最强大的依赖注入框架,业界的权威标准 ## ⛏ 功能列表 - 🐵使用 Spring 提供依赖注入与参数配置,集成 Spring 通过注解注册服务,集成 Spring 通过注解消费服务 - 🦍使用 Netty 进行网络传输,使 NIO 编程更加容易,屏蔽了 Java 底层的 NIO 细节 - 🦮基于开源的序列化框架 Protostuff / Kyro 实现消息对象的序列化/反序列化 - 🐈可优化:用户通过配置文件指定序列化方式,避免硬编码 - 🐴自定义编解码器(底层利用 Protostuff / Kyro )实现 - 🐂TCP 心跳机制 - 🐏使用 JDK / CGLIB 动态代理机制调用远程方法(调用远程方法像调用本地一样简单) - 🐪使用 Zookeeper(ZkClient 客户端)实现服务注册和发现 - 🐹客户端调用远程服务的时候进行负载均衡 :调用服务的时候,从很多服务地址中根据相应的负载均衡策略选取一个服务地址。目前使用的策略为随机负载均衡 ## 🧠设计思路 ### 🥭注册中心 - 推荐使用 Zookeeper,注册中心负责服务地址的注册与查找,相当于目录服务。服务端启动的时候将服务名称及其对应的地址(ip+port)注册到注册中心,服务消费端根据服务名称找到对应的服务地址。有了服务地址之后,服务消费端就可以通过网络请求服务端了。 - ZooKeeper 为我们提供了高可用、高性能、稳定的分布式数据一致性解决方案,通常被用于实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。并且,ZooKeeper 将数据保存在内存中,性能是非常棒的。 ### 🍊网络传输 - 既然要调用远程的方法就要发请求,请求中至少要包含你调用的类名、方法名以及相关参数吧!推荐基于 NIO 的 Netty 框架。 - Netty 是一个基于 NIO 的 client-server(客户端服务器)框架,使用它可以快速简单地开发网络应用程序,它屏蔽了 Java 底层的 NIO 细节 ### 🍏序列化和反序列化 - 在网络传输的过程中,网络传输的数据必须是二进制的,所以 Java 对象在网络中传输我们需要将其**序列化**为二进制的数据,我们需要的还是 Java 对象,所以我们还需要将二进制反序列化为 Java 对象 - 既然涉及到网络传输就一定涉及到序列化,你不可能直接使用 JDK 自带的序列化吧!JDK 自带的序列化效率低并且有安全漏洞。 所以,你还要考虑使用哪种序列化协议,比较常用的有 hession2、kyro、protostuff。 ### 🍓动态代理 - 另外,动态代理也是需要的。因为 RPC 的主要目的就是让我们调用远程方法像调用本地方法一样简单,使用动态代理可以屏蔽远程方法调用的细节比如网络传输,所以实际会通过代理对象来传输网络请求 ### 🥝负载均衡 - 当我们的系统中的某个服务的访问量特别大,我们将这个服务部署在了多台服务器上,当客户端发起请求的时候,多台服务器都可以处理这个请求,这时我们就需要负载均衡为我们避免单个服务器响应同一请求,容易造成服务器宕机、崩溃等问题 ### 🍇传输/通信协议 - 我们还需要设计一个私有的 RPC 协议(通信/传输协议),这个协议是客户端(服务消费方)和服务端(服务提供方)交流的基础。 - 通过设计传输协议,我们定义需要传输哪些类型的数据, 并且还会规定每一种类型的数据应该占多少字节。这样我们在接收到二级制数据之后,就可以正确的解析出我们需要的数据。 - 通常一些标准的 RPC 协议包含下面这些内容: - **魔数** : 通常是 4 个字节。这个魔数主要是为了筛选来到服务端的数据包,有了这个魔数之后,服务端首先取出前面四个字节进行比对,能够在第一时间识别出这个数据包并非是遵循自定义协议的,也就是无效数据包,为了安全考虑可以直接关闭连接以节省资源。 - **序列化器编号** :标识序列化的方式,比如是使用 Java 自带的序列化,还是 json,kyro 等序列化方式。 - **消息体长度** : 运行时计算出来 ## 📚 参考资料 - [SnailClimb / guide-rpc-framework](https://gitee.com/SnailClimb/guide-rpc-framework)