Monthly Archives: October 2013

Netty: 几个关键对象生命周期之间的关联

pipeline, handler, channelHandlerContext这样对象倒底是channel级的,还是event级的,又或者是系统级的? 或者这样问,一个连接中只有一个相应的实例,抑或每来一个消息都会生成一个相应的实例,又或者整个系统共享一个相应的实例?

一般来说,一个pipeline实例只属于一个channel,不会跨channel共享。因为你的pipeline factory一般会这样写:

ChannelPipeline pipeline = Channels.pipeline(); //为channel生成pipeline时总是new一个

当然,如果你有特殊需求,你也可以改变写法,让pipeline在channel间共享。下面假设你没有特殊需求,一个pipeline实例只需于一个channel.

一个channel只有一个pipeline. Channel建立时,会通过pipeline factory新生成相应的pipeline对象,ChannelPipeline pipeline = Channels.pipeline(); 后续的读写中,直接使用这个pipeline对象,不再创建新的pipeline.

由于pipeline和handler的结构关系,所以对于单种handler,一个pipeline实例中只有一个handler实例,除非你的pipeline中有重复的handler.

一个handler的实例可以只属于一个pipeline实例,

    pipeline.addLast("decoder", new HttpRequestDecoder());

也可以声明为单例,在pipeline实例间共享,也就是在多个channel间共享,这时你要注意线程安全的问题。

    pipeline.addLast("decoder", httpRequestDecoder());

pipeline实例中每新增一次handler(即使是同一个实例), 都会生成一个相应的ChannelHandlerContext实例。这里可以推出两个结论:

  1. pipeline中如果有两个handler,  那么每个handler各有各的ChannelHandlerContext对象,互不相干。

  2. 对于一个channel来说,只会生成一次pipeline,所以对于单种handler,一个pipeline实例中只有一个相应的ChannelHandlerContext实例。也就是说,对于单种handler, 相应的channelHandlerContext是channel级的,而不是event级的。

异步程序的难搞之处

1. 任务完成的顺序与代码被执行的顺序未必相同。 先调用asyncA(), 再调用asyncB(),但最后可能是B任务率先完成。

2. 有时候不知道代码走到当前此处的根本原因,给调试带来麻烦。 同步程序中,总是可以在调用栈的底部找到触发当前操作的原因,而异步程序中,走到这里可能是因为另一个线程做了什么操作,修改了公有变量,导致本线程走到这里; 那么是哪个线程做什么操作,需要对代码非常熟悉才知道。

3. Callback中出了异常,主线程往往不知道,写在主线程代码里的异常处理机制没被触发。

待续 。。。

linux最大可打开文件数的几种设置

http://johanlouwers.blogspot.de/2010/02/hard-limit-for-maximum-open-file.html

这篇文章区分介绍了user-specific/system-wide的fd limits, 以及hard limit和soft limit.

具体设置:
http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

具体设置及查看当前打开数:
http://www.randombugs.com/linux/tuning-file-descriptors-limits-on-linux.html

Mac上安装eclipse + adt + subclipse 的曲折经历

下载adt sdk后,直接用里面的eclipse加装subclipse死活装不上,试了各种方式都不行;换装subversive也装不了。

于是只好先下个普通的eclipse, 然后装subclipse很顺利; 但通过update site的方式安装adt插件又死活装不了,因为adt update site的xml叫site.xml, 而eclipse只认content.xml; 只好改用archive方式,下载adt插件,然后安装,但在安装时又出现 "Computing alternate solutions, may take a while", 暴慢无比; 只好重装,去掉“NDK”组件,突然就好了。

p.s. 今天为别人装了一次,遇到"calculate dependencies"一直停在 2%处,后来去掉 "Contract all update sites" before installing your selection"就好了

Netty的写:异步,但是可以保证顺序

Netty的写是异步的,但可以保证两个消息写出的顺序与它们在代码中被写出的先后顺序相同。

handshaker.handshake(...);   
channel.write(myFirstTextWebSocketFrame);

会不会因为异步,导致上面代码中 text frame比handshake response更先到达客户端?  答案是不会:(这人是netty开发者之一)

Netty Websocket服务端出现unsupported message type: TextWebSocketFrame

Netty Websocket服务器如果在一定程度的并发下出现下列异常并导致channel关闭:

 java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame

发生这种情况,是因为Netty Server仍处于握手状态; 在握手状态下,channel只能发送http报文,不能发送websocket帧; 如果强行发生,就会在SocketSendBufferPool.acquire()方法内抛出上述异常。

解决办法有两种:

1. 修改你的代码,确保handshake response发送完后才发出text frame

2. 回送handshake response前把websocket encoder加入到channel pipeline中,即使这时有websocket frame发出,也不会报错。– 这是作者的观点,并且他已经实现到了新版的Netty里:
https://github.com/netty/netty/commit/3b324e9515831f658fe8777df513a3a381822b34

android eclipse导入existing project出现大量红点怎么办?

android eclipse导入existing project出现大量红点怎么办?

1. 如果说"gen"目录找不到,则创建这个目录

2. 如果说“android.app"之类的找不到,则去sdk某个子目录下找到android.jar加入到build path

3. 如果说”android.support.v4"之类的找不到,则去sdk某个子目录下找到android support v4相关的一个jar包加入到build path

4. 如果说"R"类找不到,则检查一下res目录、AndroidManifest.xml是不是有错误; 如果还不行,看看project.properties里指定的target是否跟sdk版本一致。

服务端开发中的两种“异步”

服务端开发时经常会用到“异步”这个概念。要注意你说的是哪种异步,否则可能会导致沟通的误会,甚至设计的失误。

1.
客户端和服务端之间的异步交互。 客户端发出一个业务请求,服务端在这个业务请求完成之前就发出响应,然后再在后台进行处理。

2.
服务端处理请求时,在内部使用异步模式。 比如收到请求时将它丢给一个线程池来处理。

请求处理中可以同时使用这两种异步,也可以只用一种。

对于http来说,一般是“交互要同步”,但“服务端内部处理要异步”。I/O线程收到请求后,立即丢给worker线程池处理;但在worker线程处理完请求、回送响应之前,客户端要处于阻塞状态,等待响应;服务端内部使用异步处理,对客户端并没有什么好处,但它可以提高服务端自身的吞吐率。

一个常见的失误就是,一味想着“异步”,结果把一些本该同步的c/s交互也变成了异步。 最近我在处理websocket握手逻辑时就遇到这样一个问题。我们基于Netty在握手时进行了用户验证。Netty的握手API采用异步编程模型,于是我们就把验证的逻辑放到了握手API的callback中;结果 验证逻辑还没执行完,客户端就收到“握手成功”的通知,然后发出正常的业务请求。解决办法是先验证,再执行握手;如果验证逻辑采用了异步编程模型,则可以把握手API放到验证逻辑的callback中。