拓展|如何设计一个短小精悍、可拓展的RPC框架?(含实现代码)( 三 )
我把这个方法写在ApplicationContext中:
这里主要是通过动态代理来实现的,首先通过class来获取对应的机器列表,接着通过loadBalancer来选择一个机器。这个LoaderBalance是一个接口:
在ApplicationContext初始化的时候可以选择不同的实现,我这里主要实现了一个简单的随机算法(后续可以拓展为其他的,比如RoundRobin之类的):
接着构造接口方法的唯一标识identify,还有一个requestId。
为什么需要一个requestId呢?
这是因为我们在处理响应的时候,需要找到某个响应是对应的哪个请求,但是仅仅使用identify是不行的
因为我们同一个应用程序中可能会有多个线程同时调用同一个接口的同一个方法,这样的identify是相同的。
所以我们需要用 identify + requestId的方式来判断,reqeustId是一个自增的LongAddr。服务端在响应的时候会将requestId返回。
接着我们构造了一个Invoker,把它放入inProgressInvoker的集合中。调用了其invoke方法:
我们可以看到调用Invoker的invoke方法之后,会运行到waitForResult()这里,这里已经把请求通过网络发送出去了,但是就会被卡住。
这是因为我们的网络请求的结果不是同步返回的,有可能是客户端同时发起很多个请求,所以我们不可能在这里让他同步阻塞等待的。
接受响应
那么对于服务消费者而言,把请求发送出去但是卡住了,这个时候当服务端处理完之后,会把消息返回给客户端。返回的入口在
NettyClient的onChannelRead中:
这里通过callback回调出去。是否还记的我们在初始化NettyClient的时候,会设置一个callback?
这里接受消息之后,解析成为一个RpcResponse对象,然后压入responses队列中,这样我们就把所有的请求响应放入队列中。
但是这样一来,我们应该怎么把响应结果返回给调用的地方呢?
我们可以这样做:起一个或多个后台线程,然后从队列中拿出响应,然后根据响应从我们之前保存的inProcessInvoker中找出对应的Invoker,然后把结果返回回去
这里面如果从队列中拿不到数据,就会调用wait()方法等待
这里需要注意的是,在callbak中获取到响应的时候我们是会调用notifyAll()来唤醒这里的线程的:
这里被唤醒之后,就会有多个线程去争抢那个响应,因为队列是线程安全的,所以这里多个线程可以获取到响应结果。
接着拿到结果之后,通过identify + requestId构造成唯一的请求标识,从inProgressInvoker中获取对应的invoker,然后通过setResult将结果设置进去:
这里设置进去之后,就会将结果用json反序列化成为用户需要的结果,然后调用其notifyAll方法唤醒invoke方法被阻塞的线程:
然后就可以返回结果了,返回的结果就会返回给用户了。
整体测试
到了这里我们的生产者和消费者的代码都写完了,我们来整体测试一遍。生产者的代码是和之前的一致的:
消费者测试代码:
接着启动生产者,然后启动消费者:
生产者得到的日志如下:
消费者得到的日志为:
总结
通过完成这个RPC框架,大家应该会大致对RPC的实现原理有个感性的认识,这里总结一下特性:
支持多种注册中心,可配置(虽然只实现了zookeeper,但是我们拓展是非常简单的)
支持负载均衡
当然了还有非常多的不足之处,这是无可否认的,随意写出来的框架和工业级使用的框架比较还是不一样
我这里列举一些不完美的地方把(有兴趣的可以搞搞):
实现序列化框架的拓展,多种序列化供用户选择
网络请求错误处理,这里实现非常简陋,健壮性很差
注册中心不支持故障感知和自动恢复
调用监控,性能指标
加油。
END
QQ群二维码如下, 添加请注明:姓名+地区+职位,否则不予通过
【 拓展|如何设计一个短小精悍、可拓展的RPC框架?(含实现代码)】订阅我的微信公众号“杨建荣的学习笔记”,第一时间免费收到文章更新。别忘了加星标,以免错过新推送提示。
推荐阅读
- 流感|流感如何应对?听听郑州市九院儿科主任杨平怎么说的
- 蠢萌新闻|《急先锋》成龙的“接棒”杨洋,年轻演员们表现如何?
- 培训|大湾区青年创意设计 人才培训计划开班
- 观览天下|一块石头卖到十万,看村民们如何发家致富,你心动了吗?
- 乡村波比|野猪被禁止食用,农村野猪泛滥,糟蹋庄稼,该如何解决?
- 气象卫星|一文读懂风云气象卫星50年如何改变中国,未来两次发射“值得期待”
- 科学|世界3大未解之谜:生命起源、地球内核、宇宙之谜,该如何解释?
- 光速|如何超越光速?|No.227
- 崇明|如何培养“小生态人”?揭开崇明推进生态教育的“学校密码”
- 颜夕趣史|?40年前,那个站在长城喝可乐的小男孩,他后来如何了?
