26、nsq
NSQ介绍
NSQ是Go语言编写的一个开源的实时分布式的内存消息队列,性能十分优异。
有以下优势:
- 1、NSQ提倡分布式和分散的拓扑,没有单点故障,支持容错和高可用性,并提供可靠的消息交付保证。
- 2、NSQ支持横向拓展,没有任何集中式代理。
- 3、NSQ易于配置和部署,并内置了管理界面。
NSQ的使用场景
异步处理
参照下图利用消息队列把业务流程中的非关键流程异步化,从而显著降低业务请求响应时间。
应用解耦
通过使用消息队列将不同的业务逻辑解耦,降低系统间的耦合,提高系统的健壮性。后续有其他业务要使用订单数据可直接订阅消息队列,提高系统的灵活性。
流量削峰
类似于秒杀等场景下,某一时间可能会产生大量的请求,使用消息队列能够为后端处理请求提供一定的缓冲区,保证后端服务的稳定性。
安装运行NSQ
1、下载nsq docker镜像
1 | docker pull nsqio/nsq |
2、运行docker容器nsqlookupd
nslookup是维护所有nsqd状态、提供服务发现的守护进程。它能为消费者查找特定topic
下的nsqd提供了运行时的自动发现服务。他不维持持久状态,也不需要与任何其它nsqlookupd实例协调以满足查询。因此根据你系统的冗余要求尽可能多地部署nsqlookupd
节点。他们消耗的资源很少可以与其他服务共存。建议为每个数据中心运行至少3个集群。
1 | docker run -d --name nsqlookupd -p 4160:4160 -p 4161:4161 nsqio/nsq /nsqlookupd |
3、获取nsqlookupd容器ip
1 | docker inspect -f '{{.NetworkSettings.IPAddress}}' nsqlookupd |
4、运行docker容器nsqd
nsqd是一个守护进程,他接收、排队并向客户端发送消息。
broadcast-address
配置广播地址。
在搭配nsqlookupd
的情况下还需要指定nsqlookupd
的地址。
如果部署了多个nsqlokuod
节点的集群,可以指定多个nsqlookupd
的地址。
1 | docker run -d --name nsqd -p 4150:4150 -p 4151:4151 nsqio/nsq /nsqd --broadcast-address=172.17.0.6 --lookupd-tcp-address=172.17.0.6:4160 |
5、运行docker容器nsqadmin
一个实时监控集群状态、执行各种管理任务的Web管理平台。
需要制定nsqlookupd
地址。
1 | docker run -d --name nsqadmin -p 4171:4171 nsqio/nsq /nsqadmin --lookupd-http-address=172.17.0.6:4161 |
第一个-p
为tcp端口,第二个-p
为http端口,用的时候需要注意
NSQ架构
NSQ工作模式
Topic和Channel
每个nsqd实例旨在一次处理多个数据流。这些数据流称为topics
,一个topic
具有1个或多个channels
。每个channel
都会收到topic
所有消息的副本,实际上下游服务是通过对应的channel
来消费topic
消息。
topic
和channel
不是预先配置的。topic
在首次使用时创建,方法是将其发布到指定的topic
,或者订阅指定topic
上的channel
。channel
是通过订阅指定的channel
在第一次使用时创建。
topic
和chanel
都互相独立地缓冲数据,防止缓慢的消费者导致其他channel
的积压(同样适用于topic
级别)。
channel
可以并且通常会连接多个客户端。假设所有连接的客户端都处于准备接收消息的状态,则每条消息将被传递到随即客户端。
总而言之,消息是从topic -> channel
(每个channel接收该topic的所有消息副本)多播的,但是从channel —> consumer
均匀分布(每个消费者接收该channel的一部分消息)。
NSQ接收和发送消息的流程
NSQ特性
1、消息默认不持久化,可以配置成持久化模式。nsq采用的方式是内存+硬盘的模式,当内存到达一定的程度时就会将数据持久化到硬盘。
- 如果将
--mem-queue-size
设置为0,所有的消息将会储存到磁盘。 - 服务器重启时也会将当时在内存中的消息持久化。
- 如果将
每条消息至少传第一次。
消息不保证有序。
Go操作NSQ
安装
1 | go get -u github.com/nsqio/go-nsq |
生产者
1 | package main |
消费者
1 | package main |