之前也断断续续使用一些第三方IM SDK,也听说过心跳包和socketIO之类的东西。
维护时间较长的就是socket项目就是node中间层里面,使用到了ActiveMQ,至于原因是:中间层融合了多个后台,向前端提供统一的接口。其中一个后台,是比较靠近底层,类似于统一数据平台。所以每次它那边更新数据以后,中间层这边也要同步更新(且该平台每次数据更新,其它几个平台数据也需要跟着更新)。
技术总监一开始提议使用ActiveMQ。因为公司java后台项目通知java后台项目更新数据,利用的都是ActiveMQ。不过因为一开始没有使用过,担心会对项目产生什么影响,所以提出了几个骚操作:① 统一平台那边来写接口,直接操作node中间层的mongodb数据库就可以,但是那边的同事说这样很麻烦。②后来又说他那边来调用我的接口,但是他还要也要做特殊处理。不过第② 种作为了一种备选方案。
而中间层这边更新数据,需要通知统一平台的时候,则采用了中间层在操作mognodb数据的同时,调用统一平台相关接口的方案。
2. 初识ActiveMQ 2.1 下载从 ActiveMQ官网下载,可以看到node的下载
2.2 STOMP协议的简单了解上图可以看到,供node使用的activemq 版本是 STOMP 协议( Protocol)的。之前写过一篇http1.1 和http2 和 ServiceWorker 里面有提及如何通过f12的network 查看接口的Protocol。 http协议可能听说过,那么stomp协议是什么呢?
图片来源
图片来源
这里不做过多网络协议方面的探讨,可以简单理解stomp是一种通信协议。同时注意61616和61613这2个端口
从上面的下载页截图上可以看到。有4个链接:2个发送,2个接受。中间层node项目作为数据接受方,选择Receive,那么选择Queue还是Topic呢。先来看下这2个分别是什么
Queue (点对点)支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费、其它的则不能消费此消息了。当消费者不存在时,消息会一直保存,直到有消费消费
图片来源
通过和后台沟通后得知,公司项目activemq统一使用的都是 Queue。 点击Receive Queue 进去可看到有一个简单的小demo
官网的demo过于简单,可以查看
stompit的npm地址
stompit的github地址
如果觉得还不够详细,可以查看
stompit手册
项目则通过npm 下载即可
在本地和测试环境,测试的时候,没有什么问题。但是上线以后,却出现了2个大问题
3.1 无法连接上线以后通过pm2 restart项目的时候发现,项目启动不了,查看pm2 logs 发现 mq一直连接不上。
在2.1 的图里面可以看到,activemq的node版和java版本的协议和接口是不一样的。在2.2 的图里面可以看到,activemq默认端口是61616和61613
java使用的activemq端口是默认的61616端口。
而node使用使用的activemq端口是默认的61613端口
最后在运维(已离职)的帮助下,启动成功
启动成功以后,通过activemq监控台,发现node消费者过一段时间自己就消失了。node这边也没有收到断开消息,不过mq那边有重连日志。即mq 消费者变为0,而客户端没有接收到通知的问题。
WARN | Transport Connection to: tcp://xxxx:xxxfailed: java.net.SocketException: 连接超时 (Read failed) | org.apache.activemq.broker.TransportConnection.Transport | ActiveMQ Transport: tcp:///xxxx:xxx@61613
node这边也有重连,但是因为重连是写在断开回调里面的。所以没有监听到断开,自然也没有执行重新。更诡异的是,在测试的时候发现,白天一般半小时消费者就没有了。而晚上一般一晚上都不会断开,18点下班的时候重启项目后,等早上8点才断开???? 这东西是上的夜班???
3.2.2 莫名增加,拒不消失更更诡异的是 偶尔多出几个消费者,疑似中间层没有关闭干净 (有时候即使关闭中间层了,消费者还是有一个,而且这个消费者可以正常消费消息)。
3.2.3 查询资料通过查询资料,了解了一些activemq消息的知识
图片来源
图片来源
图片来源
发现有几篇文章提到消费者消失或自动断开是 ActiveMQ InactivityMonitor的问题:
使用ActiveMQ遇到了一个监听器方式的消费者一段时间会自动断开连接的问题
连接到activemq artemis时使用nodejs stompit的连接超时
配置网管.Stomp
但是运维和java的同事说,ActiveMQ的配置都是默认的。没有动过。过滤到修改配置牵涉项目很广,所以就放弃了尝试
3.2.6 莫名消失的解决由于一开始参考的是activemq 官方的简易demo,加之后期不细心(非常不细心)。所以项目其实没有配置heart-beat
图片来源
从官方的说明来看,在 ActiveMQ 5.9.0 之前客户端如果没有配置heart-beat 是无法成功连接的。但是公司项目使用的5.14版本。所以不配置也没有什么问题。所以在项目里面配置heart-beat,也不好使
最后经过调试,发现和大部分文章里面提及的不同的是 当我配置heart-beart的y=0的时候,消费者就不会莫名消失了。
'heart-beat': '6000, 0',
图片来源
所以我测试问题的最终根源是activemq生产者 会接受消费者的 mq心跳,但是不会返回给消费者,或者可以理解为我们配置的接受心跳的参数不对,可能短了。
后来我循环java同事,他们没有配置过项目的心跳,都是使用默认的。 且从项目后期稳定性来说,已经运行1年多了,也再没有出现过消费者消失的现象。
只所以会尝试设置y=0,是因为在github上有一篇issue 和我这个问题类似,如何确保客户端断开连接
关于消费者莫名增加,关闭消费者项目后,消费者仍然存在的问题。我问了java同事,他说java项目里面一般默认都设有连接池(ChannelPool)。在连接很多的情况下,连接池会自动处理的。 所以根据stompit手册.ChannelPool 的配置也使用了连接池。
项目重启了,问题得到了解决。java牛逼,java666
3.3 内存不足在项目稳定 以后,还有一个小插曲。
由于node 使用activemq ,使用的是61613端口。所以有一些本地部署的时候,需要开通61613端口。又因为中间层项目和某个后台java项目放在一个服务器上面。所以偶尔java同事会不同意开该端口。 所以只能使用之前说的统一平台调用中间层接口的s方法。
node 比起老3p(jsp,asp,php)还是有点不成熟。特别是在一些基础建设方面。node的确不是银弹



