【转】使用Netty实现多路复用的client

标签: netty 多路复用 client | 发表时间:2014-10-17 11:16 | 作者:flychao88
出处:http://www.iteye.com

       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. 1、线程A使用client发送请求

  2. 线程A从BlockingQueue中取数据。这时Queue为空,线程A等待。

  3. server接受并开启一个线程处理请求A

  4. 2、线程B使用client发送请求

  5. 线程B从BlockingQueue中取数据。这时Queue为空,线程B也等待。

  6. 3、server接受并开启另一个线程处理请求B

  7. 线程B的请求处理速度较快,先返回

  8. 4、client将返回值B写入BlockingQueue

  9. BlockQueue有数据了,线程A take到数据,但是是线程B的结果

这就导致request和response不匹配。

 

要解决这个问题有3个办法。

  1. 1、使用短连接,每次请求new一个client,接收的response后close掉这个client。这个的缺点很明显,这就相当于http服务器了,不能发挥内网长连接的优势。

  2. 2、使用连接池,每次从连接池里拿一个client,接收完response后将这个client返还连接池。这个就有点像数据库连接池。这个方法没什么缺点,但是需要自己实现连接池。

  3. 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。

  4.  

    我自己实现了第三种方式,具体代码请参见:

    https://github.com/terrymanu/miracle-framework/tree/master/miracle-framework-remote/miracle-framework-remote-netty 

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [netty 多路复用 client] 推荐:

【转】使用Netty实现多路复用的client

- - 开源软件 - ITeye博客
       Netty只提供的异步传输数据的方式,但是并没有实现多路复用的client. 一个分布式的客户端代码基本是这个样子的:. 首先通过channel发送一个请求到server,然后等待server返回的结果. 但是Netty是异步的,writeAndFlush这个方法,只是告诉server,我要发数据了,然后就马上返回了.

Netty Client重连实现

- - 鸟窝
当我们用Netty实现一个TCP client时,我们当然希望当连接断掉的时候Netty能够自动重连. Netty Client有两种情况下需要重连:. Netty Client启动的时候需要重连. 在程序运行中连接断掉需要重连. 对于第一种情况,Netty的作者在stackoverflow上给出了 解决方案,.

构建实时Web的JAVA选择组合:socket.io client + socketio-netty server

- - BlogJava-首页技术区
     摘要: 很显然,实时Web,是一种技术趋势,将成为一种人们的默认技术选择,用以拉近和桌面应用的距离. socket.io是一种数据实时推送、事件驱动模型的框架,支持事件订阅,简单易用. 其价值目前看来,还未被完整的挖掘出来. socket.io即提供了node.js服务器端(地址)又提供了客户端(地址)的整体解决方案,而socketio-netty则是基于JAVA服务器端,支持最新socket.io client最新版规范.

Zookeeper Client简介

- - zzm
直接使用zk的api实现业务功能比较繁琐. 因为要处理session loss,session expire等异常,在发生这些异常后进行重连. 又因为ZK的watcher是一次性的,如果要基于wather实现发布/订阅模式,还要自己包装一下,将一次性订阅包装成持久订阅. 另外如果要使用抽象级别更高的功能,比如分布式锁,leader选举等,还要自己额外做很多事情.

HTTP/2 in Netty

- -
Here, we created a context for the server with a JDK SSL provider, added a couple of ciphers, and configured the Application-Layer Protocol Negotiation for HTTP/2..

Netty系列之Netty高性能之道

- - CSDN博客推荐文章
最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用. 相比于传统基于Java序列化+BIO(同步阻塞IO)的通信框架,性能提升了8倍多. 事实上,我对这个数据并不感到惊讶,根据我5年多的NIO编程经验,通过选择合适的NIO框架,加上高性能的压缩二进制编解码技术,精心的设计Reactor线程模型,达到上述性能指标是完全有可能的.

Netty代码分析

- LightingMan - 淘宝JAVA中间件团队博客
Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序[官方定义],整体来看其包含了以下内容:1.提供了丰富的协议编解码支持,2.实现自有的buffer系统,减少复制所带来的消耗,3.整套channel的实现,4.基于事件的过程流转以及完整的网络事件响应与扩展,5.丰富的example.

Chrome 14 beta启用Native Client

- tinda - Solidot
Google发布了Chrome 14 beta,默认启用Native Client(NaCl),它最早在上半年发布的Chrome 10 beta整合了NaCl,但并未激活. Google在2008年首次推出了试验项目NaCl,让开发者可以编译C/C++代码为不针对特定平台的二进制文件,在浏览器整合的运行时中执行,利用沙盒技术避开安全缺陷.

剑走偏锋的 Native Client

- - 谷奥——探寻谷歌的奥秘
感谢读者  liuyanghejerry 的投稿. 不知不觉,Google已经正式推出其Native Client (NaCl)过去约7个月之久. 而目前国内似乎还没有多少关于NaCl的资料,所以在这里面向Web开发者做一下简单的介绍,希望能够起到一个抛砖引玉的效果. 本文的所有代码均来自于 https://developers.google.com/native-client/devguide/tutorial,如果您对其中的任何技术细节存在疑问,请以原文为准.

rabbitmq java client api详解

- - 五四陈科学院
以下内容由 [五四陈科学院]提供. AMQP协议是一个高级抽象层消息通信协议,RabbitMQ是AMQP协议的实现. 每个rabbitmq-server叫做一个Broker,等着tcp连接进入. 在rabbitmq-server进程内有Exchange,定义了这个消息的发送类型. Queue是进程内的逻辑队列,有多个,有名字.