Netty只提供的异步传输数据的方式,但是并没有实现多路复用的client。
一个分布式的客户端代码基本是这个样子的:
1
2
3
4
|
public Response sent( final Request request) {
channel.writeAndFlush(request);
return clientChannelInitializer.getResponse(request.getMessageId());
} |
首先通过channel发送一个请求到server,然后等待server返回的结果。
但是Netty是异步的,writeAndFlush这个方法,只是告诉server,我要发数据了,然后就马上返回了。所以这时直接调用getResponse,会得不到值。因为netty是在回调里面写返回值的。
解决的办法是,使用BlockingQueue接收返回的数据。一旦BlockingQueue有数据了,就take出来。如果没数据,就一直等待。
在单线程里,这个办法没问题。这就要确保Netty的client只被一个线程访问。如果是多线程同时访问,因为异步的原因,有可能第二个线程的返回值被第一个线程拿到。举个例子:
-
1、线程A使用client发送请求
-
线程A从BlockingQueue中取数据。这时Queue为空,线程A等待。
-
server接受并开启一个线程处理请求A
-
2、线程B使用client发送请求
-
线程B从BlockingQueue中取数据。这时Queue为空,线程B也等待。
-
3、server接受并开启另一个线程处理请求B
-
线程B的请求处理速度较快,先返回
-
4、client将返回值B写入BlockingQueue
-
BlockQueue有数据了,线程A take到数据,但是是线程B的结果
这就导致request和response不匹配。
要解决这个问题有3个办法。
-
1、使用短连接,每次请求new一个client,接收的response后close掉这个client。这个的缺点很明显,这就相当于http服务器了,不能发挥内网长连接的优势。
-
2、使用连接池,每次从连接池里拿一个client,接收完response后将这个client返还连接池。这个就有点像数据库连接池。这个方法没什么缺点,但是需要自己实现连接池。
-
3、使用单一client,但是在request中生成一个唯一的messageId,可以是nanoTime。然后server处理完后,在response中也返回这个messageId。这样在client不是维护一个BlockingQueue,而是维护一个ConcurrentHashMap,key是messageId,value是一个空的BlockingQueue。当client发送resquest到server时,在Map里写入messageId,并实例化一个BlockingQueue(为了优化,size可以是1)。然后等待这个BlockingQueue有值。在接收到response的回调方法里,根据messageId取出blockingQueue的值,然后删除掉这个Key。
-
我自己实现了第三种方式,具体代码请参见:
相关推荐
利用netty实现Modbus TCP client/server READ COILS | 0x01 READ DISCRETE INPUTS | 0x02 READ HOLDING REGISTERS | 0x03 READ INPUT REGISTERS | 0x04 WRITE SINGLE COIL | 0x05 WRITE SINGLE REGISTER | 0x06 ...
这个小程序使用netty5进行udp网络通讯,客户端有两种,1:用netty5类库发送DatagramPacket和接收 2:直接使用DatagramSocket发送接收DatagramPacket 先运行netty_server的QuoteOfTheMomentServer, 在运行netty_...
使用Netty4实现多线程的消息分发,这是一个基于netty4做的一个异步通信模型。
使用netty实现TCP长链接消息写入kafka以及kafka批量消费数据,数据可以批量进行操作
使用netty进行rtsp服务端开发 一个使用netty写的rtsp服务器。 目前支持H264、H265、 AAC格式的流文件上传与存储。 H264、H265、AAC格式流文件的播放
Netty中实现多客户端连接与通信-以实现聊天室群聊功能为例示例代码
基于Netty实现的内网穿透&反向代理的工具 (支持TCP上层协议和HTTP的穿透式反向代理).zip
他人用netty实现的一个聊天demo,包含server,client代码。代码较为简单。
NULL 博文链接:https://gjp014.iteye.com/blog/2390925
基于netty手写实现简易版tomcat,netty实现http服务器容器的demo
spring boot 整合的netty 实现的socket的demo(包括服务端和客户端是分开的两个项目,导入idea,启动即可)。
Springboot、netty实现的http-flv、websocket-flv流媒体服务(可用于直播点播),支持rtsp、h264、h265等、rtmp等多种源,h5纯js播放(不依赖flash),不需要依赖nginx等第三方,低延迟(支持识别h264、aac编码自动...
Java进阶技术-netty进阶之路
一个基于netty实现web框架,或者mvc框架,实现基于netty的web框架,你说netty强不强,文中有不对的地方,欢迎大牛指正
JAVA采用Netty库实现基于以DTU传输的TCP服务器 ,可以支持多端口通讯 ,同时也支持 多协议解析
netty http client & server 示例源码
基于Netty实现的命令行斗地主游戏,为划水摸鱼而生~ 基于Netty实现的命令行斗地主游戏,为划水摸鱼而生~ 基于Netty实现的命令行斗地主游戏,为划水摸鱼而生~ 基于Netty实现的命令行斗地主游戏,为划水摸鱼而生...
Netty实现原理浅析
springboot集成netty实现代理服务器,实现http和https请求的代理功能
一个netty建立的SSL双向加密的服务器和客户端的简单示例。工程是IDEA创建的,直接导入即可,注意需要依赖的pom文件中的包。需要的证书文件示例也在压缩包内。