项目简介: 造轮子实现"MyRPCFramework"框架
RPC介绍:
RPC是让客户端远程调用服务端方法 就像 调用本地方法一样简单的一种设计理念
一个最简单的 RPC 框架架构 :
技术要点: SPI+注册中心+Socket编程+享元模式+动态代理+反射
MyRPCFramework框架流程:
- 服务端集群 把自己能提供的服务 注册进ZooKeeper
- 客户端定义一个和服务端相同的接口, 然后生成这个接口的代理实现类, 代理负责(封装数据包, 拆解数据包, 访问ZooKeerper得到服务端ipList, 负载均衡选择一个ip进行访问)
- 服务端收到了客户端发的消息"调用xxx服务名的yyy方法", 然后通过反射调用具体实现类 去执行yyy方法, 再把返回值传给客户端
- 代理类收到返回值, 即完成了一次RPC调用
可见, 客户端只知道一个服务接口, 不知道具体实现类
项目需要改进的地方:
-
注册服务时使用SPI机制(服务发现机制)
-
使用享元设计模式 基于Thread(或Future)自定义一个线程池
-
补充负载均衡器的实现: 加权随机、加权轮循、哈希
-
轮询负载均衡时有分布式并发原子性安全问题, 可以使用ZooKeeper分布式锁
-
在访问ZooKeerper得到服务端ipList时, 若有某个ip不可用, 则进行跳过此ip 并将其移除ipList
-
链路追踪功能
把每一个 客户端访问者的ip+访问的服务+访问方法+访问时间+访问耗时 都记录下来, 基于AOP进行日志打印
如果访问耗时太久, 就记录到慢查询日志里
-
熔断功能, 若某个请求处理时长过长, 则进行服务熔断(基于Future实现的线程池有cancel方法, 可以进行终止正在运行的任务)
-
服务端使用阻塞队列接受客户端请求, 客户端请求带上priority字段
-
使用Netty作为通信框架
改进后, 项目亮点:
- 使用享元设计模式 基于Thread(或Future)自定义一个线程池
- 多种负载均衡器
- 多种序列化方式
- 自定义传输协议处理TCP粘包问题, 进行封包, 拆包
面试题:
为什么有了HTTP, 还要去用RPC?
二者不是同一个层级的东西, HTTP是网络协议, 而RPC是一种设计方案, 一种概念, 使调用远程API就像调本地方法一样简单便捷
为什么RPC不用HTTP而是去用TCP?
HTTP一般应用于 浏览器-服务端 的B/S架构, 为普通用户的浏览器 和 服务器 间提供通信, 用于对外的异构环境
TCP一般应用于 两台主机间Java进程间的通信, 用于公司内部的服务调用
-
空间占用:
HTTP1.1协议的TCP报文包含一些无用信息, 如: html标签,浏览器类型, 两台主机间Java进程间的通信 根本用不到这些东西
HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 137582 Expires: Thu, 05 Dec 1997 16:00:00 GMT Last-Modified: Wed, 5 August 1996 15:55:28 GMT Server: Apache 0.84 <html> <body>Hello World</body> </html>
-
性能消耗:
HTTP,大部分是通过 json 来实现的,效率低些
TCP,可以基于各种序列化框架进行,效率高些
-
跨平台:
HTTP:通常要求 客户端和服务器 为统一平台
TCP: 可以在各种异构系统上运行
-
HTTP连接的开销:
增加了HTTP 连接的 建立 与 断开 的开销