Fork me on GitHub

消息队列之《01.NSQ理论篇》

最近一直在做开源项目,该项目需要使用消息中间件来转储下日志、消息、监控数据、服务器上报等数据,
因此调研了下业界开源的消息队列,大致有:Kafka、Redis、Zeromq、Rebbitmq、NSQ等等;

前言

考虑到开发周期的快速迭代,没办法把以上所有队列都通透研究一遍,初步跟开源团队讨论了下,且我司也有大规模使用NSQ的场景,于是我们就决定先将NSQ吃透,NSQ在分布式和实时上确实有一定的优势,也许其他队列简单能满足我们的需求,但“杀鸡用牛刀”也是我们想去尝试的,毕竟我们的开源项目都是尊崇所用到的技术都是业界最牛逼的开源解决方案。

NSQ与其他队列对比图

(图片来之golang2017开发者大会)

NSQ介绍

  1. NSQ是一个基于Go语言的分布式实时平台,代码托管在GitHub
  2. NSQ可用于大规模系统中的实时消息服务,并且每天能够处理数亿级别的消息。
  3. NSQ具有分布式、去中心化的拓扑结构,该结构具有无单点故障、故障容错、高可用性以及能够保障消息的可靠传输的特征。
  4. NSQ非常容易配置和部署,且具有最大的灵活性,支持众多消息协议。

NSQ服务端介绍

在使用NSQ服务之前,还是有必要了解下NSQ的几个核心组件,整个NSQ服务包含三个主要部分

nsqlookupd

先看看官网的介绍:

nsqdlookup是守护进程负责管理拓扑信息,客户端通过查询nsqlookupd来发现指定话题(topic)的生产者,并且nsqd节点广播话题(topic)和通道(channel)信息

简单的理解:nsqlookupd就是中心管理服务,它使用tcp(默认度那可4160)管理nsqd服务,使用http(默认端口4161)管理nsqadmin服务,同时为客户端提供查询服务。

总的来说,nsqlookupd具有以下功能或特性:

  • 唯一性 - 在一个NSQ服务中只有一个nsqlookupd服务。当然也可以在集群中部署多个nsqlookupd,但它们之间是没有关联的
  • 去中心化 - 及时nsqlookupd崩溃,也不会影响正在运行的nsqd服务
  • 充当nsqd和nsqadmin信息交互的中间件
  • 提供一个http查询服务,给客户端定时更新nsqd的地址目录

nsqadmin

官网原话:是一套WEB UI,用来户汇聚集群的实时统计,并执行不同的管理任务

总的来说,nsqadmin具有以下功能或特性:

  • 提供一个topic和channel统一管理的操作界面以及各种实时监控数据的展示,界面设计很简介、操作也很简单
  • 展示所有message的数量,这个是装X神器
  • 能够在后台创建topic和channel,不常用
  • nsqadmin的所有功能都必须依赖于nsqlookupd,nsqadmin只是向nsqlookupd传递用户操作并展示来至nsqlookupd的数据

nsqadmin默认的访问地址是:http://127.0.0.1:4171/

nsqd

官方原话:nsqd是一个守护进程,负责接收、排队、投递消息给客户端

真正干活的就是这个服务,它主要负责message的收发,队列的维护;
nsqd会默认监听一个tcp端口(4150)和一个http端口(4151)以及一个可选的https端口

总的来说,nsqd具有以下功能或特性:

  • 对订阅了的同一个topic、同一个channel的消费者使用负载均衡策略(不是轮询)
  • 只要channel存在,即使没有该channel的消费者,也会讲生产者的message缓存到队列汇总(注意消息的过时处理)
  • 保证队列中的message至少会被消费一次,及时nsqd退出,也会讲队列中的消息暂存磁盘(结束进程等意外情况除外)
  • 限定内存使用,能够配置nsqd中的每个channel队列在内存中缓存的message数量,一旦超出,message建会被缓存到磁盘中
  • topic,channel一旦建立将会一直存在,要及时在管理台或者代码清除无效的topic和channel,避免资源浪费

下面是官方的图,第一个channel(meteics)因为有多个消费者,所以触发了负载均衡机制。后面两个channel由于没有消费者,所有的message均会被缓存在相应的队列里,直到消费者出现。

这里想到一个问题是:如果一个channel只有生产者不停的在投递message,会不会导致服务器资源被耗尽?也许nsqd内部做了相应处理,但还是要避免这种情况出现。

NSQ生产与消费

了解nsqlookupd,nsqd与客户端中消费者和生产者的关系

消费者

消费者有良好总方式与nsqd建立连接:

  • 消费者直连nsqd,这是最简单的方式,缺点是nsqd服务无法实现动态伸缩了(当然,自己去实现一个亦可以)
  • 消费者通过http查询nsqlookupd获取所有nsqd的连接地址,然后再分别和折现nsqd建立连接(官网推荐的做法,也是我司在使用的方式),但是客户端会不停的向nsqlookupd查询最新的nsqd地址目录。

官方的消费者模型:

生产者

生产者必须连接nsqd去投递message(当然,可以连接到nsqlookupd,让nsqlookupd自动选择一个nsqd去完成投递)

如果生产者所连接的nsqd挂了,那么message就会投递失败,所以在客户端必须自己实现相应的备用方案。

-------------本文结束感谢您的阅读-------------