netty实现rpc框架

Posted 还是那个徐东强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netty实现rpc框架相关的知识,希望对你有一定的参考价值。

用Netty实现了一个rpc框架(目前没有注册到zk)

代码目录如下:


快速使用如下:

rpc-demo-api中 定义service接口,以及共同的model

netty实现rpc框架

rpc-demo-provider中 

    pom中引入如下 

netty实现rpc框架

    代码中实现接口 DemoService,注解 @RemoteService 

netty实现rpc框架

    执行Provider 启动nettyServer

netty实现rpc框架

rpc-demo-consumer中 

    pom中引入

netty实现rpc框架

通过注解 @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篇

RPC框架motan: 通信框架netty

#yyds干货盘点# 基于Netty,20分钟手写一个RPC框架

手写RPC框架第二章《netty通信》

大厨小鲜——基于Netty自己动手编写RPC框架

protobuf源码解析与netty+rpc实战