# MyRPC **Repository Path**: declan1/my-rpc ## Basic Information - **Project Name**: MyRPC - **Description**: 一个自实现的PRC框架,解决了微服务之间远程调用通信的问题。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-07-31 - **Last Updated**: 2023-07-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RPC是什么 RPC即远程过程调用,能够帮助我们调用远程计算机上某个服务的方法,让这个过程就像调用本地方法一样简单,并且我们不需要了解底层网络编程的具体细节。 # 项目架构 ![输入图片说明](https://img.lovetao.top/rpc/1675517311693-c6e5caf5-dcd8-4457-8a02-7870f846a15a.png "在这里输入图片标题") ## 运行流程: 服务端 - 在服务类上添加@MyService注解 - 在容器初始化的时候,检测到带有注解的Bean后,读取注解内的信息(接口的名称以及版本号),然后**发布服务**并**启动NettyServer** - **发布服务** - - 命名服务名称(serviceName + version) - 放入服务端的Map缓存中(serviceName + version, bean),为了之后客户端调用实例 - 再注册一份放到ZK注册中心 - **启动NettyServer** - - **使用 Netty 创建工作线程和 boss 线程,绑定端口后创建 Channel 管道** - **准备接收客户端的RPCMessage** - 接收消息 - - 如果是心跳消息,返回对应的心跳消息 - 如果是请求消息,获取请求接口信息后,从 MyServiceProvider 获取服务实例Bean;调用实例后返回结果 客户端 - 在容器初始化的时候,检测每一个 Bean 的属性字段,当检测出带有MyReference 注解的字段后,**为其注入代理类**,代理要做的事情是屏蔽复杂的网络传输细节:构建请求消息、创建 Netty 客户端、接收响应结果 - 发送消息 - - 在发送消息时,获取服务端 **Channel 管道连接** - 先从 Service 缓存中获取 ZK 服务端的**IP + Port(**Service会定时的从注册中心ZK中获取健康实例并进行替换**)** - - - 获取ZK服务,用ZKClient获取所有可用的实例,然后根据负载均衡策略返回实例 - - 根据**IP + Port**在从 Channel 缓存中获取 Channel 连接 - 发送消息,接收结果 ## 使用的技术 ## 注册中心 注册中心负载服务地址的注册与查找,相当于目录服务。服务端启动的时候将服务名称及其对应的地址(ip + port)注册到注册中心,服务端根据服务名称找到对应的服务地址。有了服务地址之后,服务消费端就可以通过网络请求服务端了。 ## 序列化反序列化 因为只有二进制才能在网络中进行传输,所以为了方便网络通信,必须得把对象转换为二进制数据才行。另外,不仅网络传输的时候需要用到序列化和反序列化,将对象存储到文件、数据库等场景都需要用到序列化和反序列化。 ## 动态代理 RPC的主要目的就是让我们调用远程方法像调用本地方法一样简单,我们不需要关心远程方法调用的细节比如网络传输。 怎样才能屏蔽远程方法调用的底层细节呢?答案就是动态代理。简单来说,当你调用远程方法的时候,实际会通过代理对象来传输网络请求,不然的话,怎么可能直接就调用到远程方法。 ## 负载均衡 我们的系统中的某个服务的访问量特别大,我们将这个服务部署在了多台服务器上,当客户端发起请求的时候,多台服务器都可以处理这个请求。那么,如何正确选择处理该请求的服务器就很关键。假如,你就要一台服务器来处理该服务的请求,那该服务部署在多台服务器的意义就不复存在了。负载均衡就是为了避免单个服务器响应同—请求,容易造成服务器宕机、崩溃等问题,我们从负载均衡的这四个字就能明显感受到它的意义。 ## 传输协议 通过设计协议,我们定义需要传输哪些类型的数据,并且还会规定每一种类型的数据应该占多少字节。这样我们在接收到二进制数据之后,就可以正确的解析出我们需要的数据。 具体协议: 1. 4B magic code(魔法数) 2. 1B version(版本) 3. 4B full length(消息长度) 4. 1B messageType(消息类型) 5. 1B codec(序列化类型) 6. 1B compress(压缩类型) 7. 4B requestId(请求的Id) 8. body(object类型数据)