Nsq服务端简介

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

nsqlookupd

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

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

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

  • 唯一性,在一个Nsq服务中只有一个nsqlookupd服务。当然也可以在集群中部署多个nsqlookupd,但它们之间是没有关联的
  • 去中心化,即使nsqlookupd崩溃,也会不影响正在运行的nsqd服务
  • 充当nsqd和naqadmin信息交互的中间件
  • 提供一个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获取该nsqlookupd上所有nsqd的连接地址,然后再分别和这些nsqd建立连接(官方推荐的做法),但是客户端会不停的向nsqlookupd查询最新的nsqd地址目录(不喜欢用http轮询这种方式...)
    还是看图更直接些 ,官方的消费者模型:

生产者

生产者必须直连nsqd去投递message(网上说,可以连接到nsqlookupd,让nsqlookupd自动选择一个nsqd去完成投递,但是我用Producer的tcp是连不上nsqlookupd的,不知道http可不可以...),

这里有一个问题就是如果生产者所连接的nsqd炸了,那么message就会投递失败,所以在客户端必须自己实现相应的备用方案

安装Nsq

方法一

  • 首先搭建golang开发环境,这里就不详细讲了

    • 注意一下,搭建golang环境时最好将bin目录添加到系统环境(path)里,省去了每次都要去bin目录里执行的麻烦
  • 安装包管理器godep
go get github.com/tools/godep

执行完后检查godep是否已经安装在bin目录下,一般都会自动安装,如果没有,用go install手动安装下

  • 安装依赖包assert
go get github.com/bmizerany/assert
  • 安装Nsq
godep get github.com/bitly/nsq/...

如果安装成功,bin目录里就会出现一大堆nsq_...开头的可执行文件

  • PS:如果安装失败

    • 像我一样出现了一大堆"use of internal package not allowed"错误,找了半天,才在一个角落里发现了这句话
      注意:NSQ 保持了 go get 兼容,但是不推荐,因为之后不能保证仍然能稳定编译。

    这时采用方法二安装

方法二

运行Nsq服务集群

  • 首先启动nsqlookud
nsqlookupd
  • 启动nsqd,并接入刚刚启动的nsqlookud。这里为了方便接下来的测试,启动了两个nsqd
nsqd --lookupd-tcp-address=127.0.0.1:4160
nsqd --lookupd-tcp-address=127.0.0.1:4160 -tcp-address=0.0.0.0:4152 -http-address=0.0.0.0:4153

这里有个小问题,在windows上直接执行就能启动多个nsqd,但是在linux下(我自己用的是ubuntu),需要切换路径执行,不然会出现如下错误

[nsqd] 2019/02/12 18:46:31.761875 FATAL: --data-path=/home/miracle in use (possibly by another instance of nsqd)
  • 启动nqsadmin
nsqadmin --lookupd-http-address=127.0.0.1:4161

基于go-nsq的客户端实现

几个值得注意的地方

  • Producer断线后不会重连,需要自己手动重连,Consumer断线后会自动重连
  • Consumer的重连时间配置项有两个功能(这个设计必须吐槽一下,分开配置更好一点)

    • Consumer检测到与nsqd的连接断开后,每隔x秒向nsqd请求重连
    • Consumer每隔x秒,向nsqlookud进行http轮询,用来更新自己的nsqd地址目录
    • Consumer的重连时间默认是60s(...菜都凉了),我改成了1s
  • Consumer可以同时接收不同nsqd node的同名topic数据,为了避免混淆,就必须在客户端进行处理
  • 在AddConurrentHandlers和 AddHandler中设置的接口回调是在另外的goroutine中执行的
  • Producer不能发布(Publish)空message,否则会导致panic

go_nsq-send.go

//Nsq发送测试
package main import (
"bufio"
"fmt"
"github.com/nsqio/go-nsq"
"os"
) var producer *nsq.Producer // 主函数
func main() {
strIP1 := "127.0.0.1:4150"
strIP2 := "127.0.0.1:4152"
InitProducer(strIP1) running := true //读取控制台输入
reader := bufio.NewReader(os.Stdin)
for running {
data, _, _ := reader.ReadLine()
command := string(data)
if command == "stop" {
running = false
} for err := Publish("test", command); err != nil; err = Publish("test", command) {
//切换IP重连
strIP1, strIP2 = strIP2, strIP1
InitProducer(strIP1)
}
}
//关闭
producer.Stop()
} // 初始化生产者
func InitProducer(str string) {
var err error
fmt.Println("address: ", str)
producer, err = nsq.NewProducer(str, nsq.NewConfig())
if err != nil {
panic(err)
}
} //发布消息
func Publish(topic string, message string) error {
var err error
if producer != nil {
if message == "" { //不能发布空串,否则会导致error
return nil
}
err = producer.Publish(topic, []byte(message)) // 发布消息
return err
}
return fmt.Errorf("producer is nil", err)
}

go_nsq-receive.go

 
//Nsq接收测试
package main import (
"fmt"
"time" "github.com/nsqio/go-nsq"
) // 消费者
type ConsumerT struct{} // 主函数
func main() {
InitConsumer("test", "test-channel", "127.0.0.1:4161")
for {
time.Sleep(time.Second * 10)
}
} //处理消息
func (*ConsumerT) HandleMessage(msg *nsq.Message) error {
fmt.Println("receive", msg.NSQDAddress, "message:", string(msg.Body))
return nil
} //初始化消费者
func InitConsumer(topic string, channel string, address string) {
cfg := nsq.NewConfig()
cfg.LookupdPollInterval = time.Second          //设置重连时间
c, err := nsq.NewConsumer(topic, channel, cfg) // 新建一个消费者
if err != nil {
panic(err)
}
c.SetLogger(nil, 0)        //屏蔽系统日志
c.AddHandler(&ConsumerT{}) // 添加消费者接口 //建立NSQLookupd连接
if err := c.ConnectToNSQLookupd(address); err != nil {
panic(err)
} //建立多个nsqd连接
// if err := c.ConnectToNSQDs([]string{"127.0.0.1:4150", "127.0.0.1:4152"}); err != nil {
//  panic(err)
// } // 建立一个nsqd连接
// if err := c.ConnectToNSQD("127.0.0.1:4150"); err != nil {
//  panic(err)
// }
}

Go:Nsq消息队列的更多相关文章

  1. 剖析nsq消息队列(一) 简介及去中心化实现原理

    分布式消息队列nsq,简单易用,去中心化的设计使nsq更健壮,nsq充分利用了go语言的goroutine和channel来实现的消息处理,代码量也不大,读不了多久就没了.后期的文章我会把nsq的源码 ...

  2. 剖析nsq消息队列(二) 去中心化代码源码解析

    在上一篇帖子剖析nsq消息队列(一) 简介及去中心化实现原理中,我介绍了nsq的两种使用方式,一种是直接连接,还有一种是通过nslookup来实现去中心化的方式使用,并大概说了一下实现原理,没有什么难 ...

  3. 剖析nsq消息队列(四) 消息的负载处理

    剖析nsq消息队列-目录 实际应用中,一部分服务集群可能会同时订阅同一个topic,并且处于同一个channel下.当nsqd有消息需要发送给订阅客户端去处理时,发给哪个客户端是需要考虑的,也就是我要 ...

  4. 剖析nsq消息队列目录

    剖析nsq消息队列(一) 简介及去中心化实现原理 剖析nsq消息队列(二) 去中心化源码解析 剖析nsq消息队列(三) 消息传输的可靠性和持久化[一] 剖析nsq消息队列(三) 消息传输的可靠性和持久 ...

  5. NSQ消息队列

    前面的总结中提到过这个玩意,所以简单说说,win上面的测试验证 网上有比较合适的博文,我先推荐几篇 https://blog.csdn.net/a2247889821/article/details/ ...

  6. 消息队列 NSQ 源码学习笔记 (一)

    nsqlookupd 用于Topic, Channel, Node 三类信息的一致性分发 概要 nsqlookup 知识点总结 功能定位 为node 节点和客户端节点提供一致的topic, chann ...

  7. 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)

    Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...

  8. 消息队列Queue大全

    消息队列Queue大全 (http://queues.io/) 作业队列,消息队列和其他队列.几乎所有你能想到的都在这. 关于 那里有很多排队系统.他们每个人都不同,是为解决某些问题而创建的.这个页面 ...

  9. 消息队列&Celery&RabbitMQ&zeromq

    一.消息队列 什么是消息队列? “消息队列”是在消息的传输过程中保存消息的容器. “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象. 消息 ...

随机推荐

  1. c# ListBox

    1. ListBox用法(http://www.cnblogs.com/chinahbzm/articles/3577285.html) 2. ListBox使用(http://www.cnblogs ...

  2. Twitter的流处理器系统Heron——升级的storm,可以利用mesos来进行资源调度

    2011年,Twitter发布了开源的分布式流计算系统Storm.四年后,随着用户数量的急剧增加,Twitter每天要处理的事件已经增加到十亿以上.Storm系统应对如此庞大而复杂多样的流数据变得十分 ...

  3. adb命令(二)

    1.获取手机型号指令 adb shell cat /system/build.prop | findstr "ro.product.model" 2.获取手机处理器信息 adb s ...

  4. Convolutional Neural Networks for Visual Recognition 4

    Modeling one neuron 下面我们开始介绍神经网络,我们先从最简单的一个神经元的情况开始,一个简单的神经元包括输入,激励函数以及输出.如下图所示: 一个神经元类似一个线性分类器,如果激励 ...

  5. freeMarker(十三)——XML处理指南之揭示XML文档

    学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net 前言 尽管 FreeMarker 最初被设计用作Web页面的模板引擎, ...

  6. xdebug浏览器调试参数

    XDEBUG_SESSION_START=phpstorm-xdebug 找到对应PHP版本的 Xdebug ,后面带 TS 的为线程安全,本机环境为 win7 64 + php-5.5.1-Win3 ...

  7. Parallel Programming-使用CancellationTokenSource调度并行运行的Task

    本文主要介绍使用CancellationTokenSource调度并行运行的Task. 一.使用场景 有多个Task并行运行时,如果其中一个Task所运行的程序出现异常,我们想马上终止所有待执行的Ta ...

  8. unittest ,ddt数据驱动,读取文件中数据,多个参数时的处理

    1. test.yaml中的数据 这里的属性是list 2.创建用例 3,在yaml中创建数据,创建list数据,list中再创建dict数据,这样就可以读取dict中的多个参数的数据了

  9. MyEclipse、Eclipse SVN插件的帐号、密码修改

    问题描述: Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能.但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号.密 ...

  10. spring 学习 requestMapping

    1:    @RequestMapping:处理请求地址映射的请求,有6个属性? `         value:   URL 地址  method:   GET/POST/PUT/DELETE co ...