Monthly Archives: November 2013

为什么要做模块分拆?

为什么大类要拆成小类?为什么要把系统拆成多个模块?

以下列举出的原因都是老生常谈,对很多人来说都是直觉的东西; 直觉的坏处是:如果它成直觉了,你反而说不出它有什么好处了,当争论来临时,你就无法说服你的同事了。

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连接。