有必要搞pipeline之类的东西吗?

有必要搞pipeline之类的东西吗? 把各块功能封装成独立的API,然后每个request handler分别调用不同的api组合不就行了吗?这样还免得搞框架,也不用写什么配置文件。 这种质疑不是没有道理,但最近的亲身体会表明,pipeline体系在开发效率、代码正确率上有确有一定优势。 比方说,要加一个切面功能的话,Pipeline模式中开发者要在各个request handler的xml配置中加上一行,API模式中开发者要修改各个 request handler类。 比较: 1. 在xml中加配置肯定比在各个类中加代码更快 2. 在xml中加不易出错,而在各个类代码中改相对容易出错     a. java代码在结构上不如xml文件清晰,插错地方的可能性比较高     b. 在java代码中新增API调用语句前要先收集输入,如果插入点的上下文没有直接可用的变量作为输入,则需要重构代码,引发bug隐患; 在xml中配置没有这个问题,因为pipeline体系中强制规定了输入变量应从pipeline context中获取,总是能获取到的。     c. 在java代码中调用API后要根据输出和异常决定下一步怎么走,这可能导致比较大的流程变更,而且不同的request handler需要做不同的变更,这非常容易出错; 在xml中配置没有这个问题,因为pipeline体系各valve自己已经决定了下一个出口,不需要调用者操心。 总结一下,pipeline体系中的处理结点是特殊的API,它们有高度统一的接口和更高的自恰性,组装起来比普通API更容易,所以应对功能变更的能力也更强。

为什么要做模块分拆?

为什么大类要拆成小类?为什么要把系统拆成多个模块? 以下列举出的原因都是老生常谈,对很多人来说都是直觉的东西; 直觉的坏处是:如果它成直觉了,你反而说不出它有什么好处了,当争论来临时,你就无法说服你的同事了。 1. 大变小,能使部分功能可重用。如果所有功能的揉在一起,那一般就没有专们针对某小块功能的接口,外界无法直调这块功能,也就无法重用。 2. 模块拆分,实际上强制实施了封装性,使得模块之间只能通过有限的接口互相访问,从而降低耦合。耦合的意思是:一样东西变时,另一样东西不必变;拆分后,一个模块的变动如果不影响接口,其它的模块就不用变; 如果未拆分,一个功能可能全身都是接口,每处都有可能被其他功能依赖,自己任意一个小变都会导致其他模块跟着变。 3. Separation of Concern, 即分离关注点,每个团队、每个人只需要关注、维护系统的一部分模块或一个子系统。这在大中型组织中非常重要,对开发效率的影响是全方位的。它可以降低开发人员的系统知识门槛,并使得每个模块都有相应的精熟者,对开发效率的影响不言而喻。 4. 最后,模块拆分对开发环境、配置管理、运行维护也很重要。如果一个代码库过大,svn checkout一下,编译一下,可能半小时就过去了; 如果系统未做拆分,一个哥们提交了一行错误代码导致编译错误,会使得整个团队都无法继续开发; 如果整个应用作为单个进程运行,那么某块功能一挂,整个应用都挂,比如某个垂直频道压力过大,导致进程异常退出,那么压力不大的其他频道也没法访问了。

Aspirin: 不用指定任何smtp服务器,用JAVA发email

https://github.com/masukomi/aspirin 可以帮你发出email,  不用你显式指定一个smtp服务器。 API也非常简单。 看了一下它的源码,原来它的原理是: 当你指定收件人为xxx@yyy.com时,它会试着去DNS上找一下yyy.com对应的MX记录,作为临时的smtp server:   MX = a type of resource record in the Domain Name System that specifies a mail server responsible for accepting email messages on behalf of a recipient’s domain

长连接交互中的连接恢复与异常处理

1. 客户端应该有自动重连机制,或者,在需要发送业务数据前如果发现连接已断开,则重连。 2. 有一种极端的情况是,服务端出问题关闭连接,客户端立即重连,由于服务端问题还没修复,客户端重连上后马上又断开。。。如果并发很高的话,服务端会不堪重负。 解决办法是客户端应逐渐重连间隔,第二次重连在第一次5秒后,第三次在10秒后,第N次在1分种后。。。 3. 服务端出现异常如何处理?如果确定当前处于request/reply语境下,则应该回送当前操作相应的错误报文(就像web服务器的http 500); 否则,应该关闭连接。为什么这时要关闭连接?    a. 如果你写一个错误报文给客户端,那么客户端可能并不知道这个错误针对的是哪个请求,因为客户端可能并没有主动请求,是服务端主动发下行消息时才出的错。    b. 如果你不关闭连接,什么也不干,客户端可能会陷入无限等待,因为当前可能正处于request/reply语境下,服务端却不知道。 比如,netty handler中执行到exceptionCaught()方法时,并不知道自己处于哪种语境下。

Mac下为Safari设置外网socks代理,导致java程序中的内网socket访问全部失败

今天遇到一个问题:Mac下为Safari设置外网socks代理,导致java程序中的内网socket访问全部失败。 刚出现这个问题时觉得很诡异。一个内网URL地址,用chrome浏览器 + switchy proxy # (置为no proxy)可以访问,而用java程序中的URLConnection或Socket代码连网络都会失败。 后来跟进Socket代码才发现原因。 教训就是: Safari所设置的socks代理是系统级的,不仅影响safari,还影响整个系统所有的socks连接。

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级的。

收藏:特殊IP地址段

一个结点要向注册中心告知自己的IP,应该用本机多个IP中的哪个? 看这里 http://en.wikipedia.org/wiki/Reserved_IP_addresses,避免使用虚拟IP、多播IP和回环IP.

异步程序的难搞之处

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