netty实现rpc框架
Posted 还是那个徐东强
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netty实现rpc框架相关的知识,希望对你有一定的参考价值。
用Netty实现了一个rpc框架(目前没有注册到zk)
代码目录如下:
快速使用如下:
rpc-demo-api中 定义service接口,以及共同的model
rpc-demo-provider中
pom中引入如下
代码中实现接口 DemoService,注解 @RemoteService
执行Provider 启动nettyServer
rpc-demo-consumer中
pom中引入
通过注解 @Reference 注入service,执行 测试集
知识点如下:
1.netty client server 模板化的代码了解一下 以及
tcp 拆包粘包问题: 主要有四种解决方案
消息定长
换行符作为结束符(demo中用此)
特殊字符作为结束符
自定义协议,比如在消息头中指定消息的长度
2.执行rpc-demo-consumer中的测试集的时候,通过 BeanPostProcessor 可以扩展bean
对其中字段上注解 @Reference 的对象,建立代理,执行代理service的方法时,等同于通过Netty Client向服务器端发送请求。
rpc-demo-provider中的Provider启动的时候,注解了@RemoteService的service 以key=service名称,value=service对象,map存到内存中。
consume请求中包含了interfaceName,methodName等等,从map中获取到对应的service过FastClass反射,返回结果。
3.Netty Client连接Server的方式主要有三种
短链接:每次netty client发送请求到Server的时候都创建一个全新的链接
长链接:链接一次,通道不断开一致使用
特殊的长链接:在长链接上修改,如果在指定的时间内没有任何通信,则关闭通道,减少服务器端资源占用(代码中采用)
4.由于是长链,就需要考虑请求和响应的正确匹配,方案如下:
客户端请求和服务器端响应均包含了唯一的 RequstId,客户端发送请求后将 <请求ID,Future>的键值保存在一个全局的Map中,阻塞等待结果,当NettyClient接收都请求的时候,根据requestId从全局Map中取出Future,设置响应结果,唤醒之前阻塞,返回结果。
可以使用ReentrantLock 来实现阻塞唤醒(参见AsyncFuture),而可以使用 CountDownLatch来实现(参见SyncFuture)
残留问题:
回到之前的测试用例5,如下奇怪的现象,原因不明,悬案??待查明。
使用的长链接(设置5秒没有任何通信则断开链接)
通过Thread.sleep让服务端的执行时间为700ms,在客户端发起10个请求,发现在执行到i=6的时候,服务器端执行完了的日志打印出来了,但是客户端始终等待,NettyClientHandler中的readChannel使用没有接收到相应。
如果设置了超时时间,没有接收到响应,则返回空。则i=6的请求结果为空,后续请求重新建立链接,结果正常。
服务器端:
mianhua_0====b58589f3-c127-4e80-86b4-1844b3356007 执行完毕....
mianhua_1====8357115b-269f-4339-9aa2-eabf431bb775 执行完毕....
mianhua_2====e3bfb862-bedf-4e32-aab0-591636895a7f 执行完毕....
mianhua_3====b06e7e66-4ec0-4edb-abc6-49509fbd1e3e 执行完毕....
mianhua_4====51620b52-aff0-424f-a7b8-26d2870cb178 执行完毕....
mianhua_5====a1450082-f7cb-44b4-8e5c-22ed51a09200 执行完毕....
mianhua_6====32fdcf6c-747e-4b4d-8f18-100c137cf1ae 执行完毕....
mianhua_7====a1525b43-54ed-4a41-8582-202278037cf2 执行完毕....
mianhua_8====f3063219-d16f-4911-90a2-774f80631546 执行完毕....
mianhua_9====550477fa-ed73-459d-95d5-8d3518b76fae 执行完毕....
客户端:
远程服务器已经连接, 可以进行数据交换..
b58589f3-c127-4e80-86b4-1844b3356007接收到请求....
mianhua_0====sayHello! mianhua_0
8357115b-269f-4339-9aa2-eabf431bb775接收到请求....
mianhua_1====sayHello! mianhua_1
e3bfb862-bedf-4e32-aab0-591636895a7f接收到请求....
mianhua_2====sayHello! mianhua_2
b06e7e66-4ec0-4edb-abc6-49509fbd1e3e接收到请求....
mianhua_3====sayHello! mianhua_3
51620b52-aff0-424f-a7b8-26d2870cb178接收到请求....
mianhua_4====sayHello! mianhua_4
a1450082-f7cb-44b4-8e5c-22ed51a09200接收到请求....
mianhua_5====sayHello! mianhua_5
mianhua_6====null
远程服务器已经连接, 可以进行数据交换..
a1525b43-54ed-4a41-8582-202278037cf2接收到请求....
mianhua_7====sayHello! mianhua_7
f3063219-d16f-4911-90a2-774f80631546接收到请求....
mianhua_8====sayHello! mianhua_8
550477fa-ed73-459d-95d5-8d3518b76fae接收到请求....
mianhua_9====sayHello! mianhua_9
若要保留这种链接,如何结果该问题。
直接换成长链接,不存在此问题。
代码上传到码云如下:
https://gitee.com/XuDongQiang/netty-rpc.git
以上是关于netty实现rpc框架的主要内容,如果未能解决你的问题,请参考以下文章
基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇