ZeroMQ的想法和初衷是好的,让你用串行的思路写异步的消息处理程序。并且在此基础之上提炼出了常见的消息模式,让你写起程序来更加省心。库替你完成了异步消息发送、故障恢复、甚至连磁盘的buffer都提供了。不可谓不全面。同时提供的接口非常简洁。
但是,用很少的接口封装复杂的逻辑通常的结果就是:当你的业务场景跟库的设计者设想的业务场景一样时,你回很爽。但当业务有差别,或者对细节有要求时,你会很惨。用trick能解决已经算是较好的情况了。
欺骗性质的封装。
当你zmq_connect返回成功的时候,不要高兴,这并不意味着你真的创建好链接了,因为即使你连一个根本没人监听的地址也会成功,为什么呢,因为ZeroMQ认为它提供了故障恢复自动重连的机制。后面会自动重连上的。可是如果是地址错了或者对方挂了,这辈子都不会连上了,这库就傻掉了。
再比如,你发个消息,又返回成功,也不要高兴,这并不意味着对方已经能收到了。因为消息是异步发送的,而且ZeroMQ提供了消息缓存,暂时发不出去,ZeroMQ认为后面是能发得出去的。于是消息被缓存起来。于是你想设下这个缓存,发现最低为1,也就是说至少缓存一条消息。如果这消息发不出去,你也收不回来。程序如果要停,消息就丢了。这跟ZeroMQ实现异步的方式有关。ZeroMQ是用线程的方式实现异步的。如果不缓存到IO线程,那还怎么个异步法。
过度抽象且不提供细节。
ZeroMQ建立在socket之上,隐藏了细节。但是,有时候当你需要这些细节的时候,就很纠结了。比如我收到一个消息,我想知道底层连接的信息,似乎是不大可能的,因为一个ZeroMQ套接字后面可能有很多底层的套接字(而且你不可控,也不可知)。类似的情况还有不能访问消息缓冲等等。
总之,ZeroMQ把网络通信从头到脚封装了一遍,提供了一个整体的解决方案。如果我们全盘接受这个解决方案,那么没有问题,但如果只需要一部分,并且对其他部分有要求,那么会很难受。如果应用场景稍微底层一些就会发现,本来可靠的tcp被这么一封装变得不可靠了,只能把它当作一个高级的UDP来用,弱要强调消息传输的可靠性,还需要用户做很多工作。略显无奈。
当然,一下抱怨也是基于特定场景(在一些场景下ZeroMQ还是很完美的)。说明ZeroMQ本不是为此而生。又何必强求。但是官方的态度似乎是想将它做成新一代的通用的socket,这应该还有很长的路要走。