当nsq跑起来之后, 我们可能会遇到以下问题

分布式部署

处理错误(何时requeue)

如何使用golang lib

抱着不应该只停留在入门的态度, 笔者粗浅的研究了一下这几个问题, 希望也对有同样疑问的人有帮助.

部署

由于NSQ的分布式网络结构, NSQD必须广播(到lookup)自己的地址并让消费者连接, 那么多个NSQD无法做透明负载均衡.

就必须为每一个NSQD分配单独的IP(或host)以保证消费者(在lookup找到NSQ节点)能够正确的连接. 这样部署起来可能会麻烦一些 但问题不大, 注意一下就好.

ps: 如果有更好的方法请告诉我, 小弟感激不尽.

NSQ Requeue And Backoff

建议结合官方文档来看

requeue(重试)

用于当错误发生, 需要重试时.

backoff(避退)

backoff能降低消费者吞吐量以让消费者从错误中恢复.

当消费者在backoff状态时, 这个消费者将不再处理任何消息, 直到backoff超时

当触发backoff时控制台将打印:

// 进入backoff状态, RDY设置为0代表准备接收0条消息(不接收消息) (协议详情看 https://nsq.io/clients/tcp_protocol_spec.html)

WRN 1 [test/test] backing off for 1m4s (backoff level 6), setting all to RDY 0

// 时间到了将设置RDY为1接收1条消息以测试状态, 官方将这个状态称为`tests the waters`

WRN 1 [test/test] (DESKTOP-HELJ7V4:4150) backoff timeout expired, sending RDY 1

当有多个消费者竞争时, 出错的消费者应当主动backoff不再处理消息(以让出更多的机会给其他消费者).

如果只有一个消费者, 则消费者会等到backoff超时后才开始处理消息(空出时间让消费者恢复).

避退是存在于整个消费者上的, 所以消费者每当一个消息处理失败了之后都会增加这个消费者的backoff level. 这会影响这个消费者的处理能力.

到底需不需要用backoff, 就要看业务了:

消息是用来更新数据库订单状态的, 这是一个不容易出错的逻辑, 如果需要requeue则需要backoff让出优先级, 让其他消费者来做, 尽量以挽救这个订单.

消息是用来通知第三方(如支付宝支付成功的http回调)的, 一般requeue是发生在第三方端响应不满足预期的响应, 这不是我方消费者的错误, 应当不使用backoff, 避免阻塞消息消费.

参考:

golang lib

nsq提供golang的client lib. 支持全部特性.

本着不重复造轮子原则, 我也想尽大可能的使用nsq lib里的代码逻辑来实现需求, 但有些需求它实现不了, 我也只好自己写代码了.

先看看它原有的几个逻辑

消息自动重试

// Handler is the message processing interface for Consumer

//

// Implement this interface for handlers that return whether or not message

// processing completed successfully.

//

// When the return value is nil Consumer will automatically handle FINishing.

//

// When the returned value is non-nil Consumer will automatically handle REQueing.

type Handler interface {

HandleMessage(message *Message) error

}

消息自动重试与判断失败

func (r *Consumer) handlerLoop(handler Handler) {

r.log(LogLevelDebug, "starting Handler")

for {

message, ok :=

if !ok {

goto exit

}

if r.shouldFailMessage(message, handler) {

message.Finish()

continue

}

err := handler.HandleMessage(message)

if err != nil {

r.log(LogLevelError, "Handler returned error (%s) for msg %s", err, message.ID)

if !message.IsAutoResponseDisabled() {

message.Requeue(-1)

}

continue

}

if !message.IsAutoResponseDisabled() {

message.Finish()

}

}

exit:

r.log(LogLevelDebug, "stopping Handler")

if atomic.AddInt32(&r.runningHandlers, -1) == 0 {

r.exit()

}

}

判断失败

func (r *Consumer) shouldFailMessage(message *Message, handler interface{}) bool {

// message passed the max number of attempts

if r.config.MaxAttempts > 0 && message.Attempts > r.config.MaxAttempts {

r.log(LogLevelWarning, "msg %s attempted %d times, giving up",

message.ID, message.Attempts)

logger, ok := handler.(FailedMessageLogger)

if ok {

logger.LogFailedMessage(message)

}

return true

}

return false

}

requeue

可以看到当handler返回的error不为空时, nsq将自动requeue, 这种重试是很方便但是

使用这个重试机制的坏处是:

不能自定义requeue的等待时间(默认等待时间=config.DefaultRequeueDelay*Attempts)

会在控制台打印一个ERR(不能自定义格式, 而且有一些err不应该打印到控制台), 这点可能有洁癖的开发者受不了.

一些错误不应该重试, 如入参不合法, 再怎么重试也是徒劳. 这时候应该直接失败.

所以我建议不要使用这个err机制, 而应当手动使用msg.Requeue(-1)或者msg.RequeueWithoutBackoff(-1) 来显示指定requeue.

shouldFailMessage

我们可以使用 FailedMessageLogger interface自定义当消息失败时的处理方式.

但它的shouldFailMessage又有什么需求满足不了呢?

在失败的时候拿到最后一次错误信息

shouldFailMessage只能判断处理重试次数过多的失败, 不能处理直接失败的消息.

所以又只有自己实现啦:

我们直接在Handler中判断Attempts来实现错误处理.

但为了保证我们的消息不被shouldFailMessage处理, 需要配置MaxAttempts为0或者一个比较大的数.

nsq php,Nsq从入门到实践相关推荐

  1. 计算机编程书籍-Python硬件开发树莓派从入门到实践无人驾驶 AndroidTV 自动循迹

    内容简介 <Python硬件开发树莓派从入门到实践>全书可大致分为4个部分,其中第13章介绍了树莓派的基本使用:第4章介绍了如何在树莓派上使用Python的OpenCV包:第58章介绍了树 ...

  2. 免费送书啦!《 OpenCV图像处理入门与实践》一本全搞定

    OpenCV 的基础图像操作都只是针对图像中的像素点,并不是直接对图像整体进行的操作.而很多时候并不能仅通过改变像素点来进行图像的操作,为此我们需要学习关于图像的算术操作. 1.图像加法 对于两张相同 ...

  3. python快速编程入门课后简答题答案-Python编程:从入门到实践(第2版)第1章习题答案...

    <Python编程:从入门到实践>是一本不错的书.第2版已经公开预售,预计会在10月份正式上市. 动手试一试 本章的练习都是探索性的,但从第2章开始将要求你用那一章学到的知识来解决问题. ...

  4. python入门到实践-一本书搞定Python入门到实践

    上周介绍了几本Python从入门到进阶书籍,今天继续推荐好书,这本书是<Python编程:从入门到实践>.入门 Python 最好的书之一,适合零基础小白,也适合有其它语言背景的程序员 书 ...

  5. python如何导入txt数据集-终于找到python入门到实践数据集

    Python是一款功能强大的脚本语言,具有丰富和强大的库,重要的是,它还具有很强的可读性,易用易学,非常适合编程初学者入门.以下是小编为你整理的python入门到实践数据集 环境配置:下载Python ...

  6. python编程 从入门到实践怎么样-python编程从入门到实践这本书怎么样

    <Python编程-从入门到实践>作者: Eric Matthes,已翻译为中文,人民邮电出版社出版. python编程从入门到实践怎么样? 我们一起看看已经学习的同学对这本书的口碑和评价 ...

  7. python编程入门到实践 百度云-python网络爬虫从入门到实践pdf

    python网络爬虫从入门到实践pdf是一本非常热门的编程教学.这本书籍详细讲解了Python以及网络爬虫相关知识,非常适合新手阅读,需要的用户自行下载吧. Python网络爬虫从入门到实践电子书介绍 ...

  8. python编程入门指南怎么样-python编程从入门到实践这本书怎么样

    <Python编程-从入门到实践>作者: Eric Matthes,已翻译为中文,人民邮电出版社出版. python编程从入门到实践怎么样? 我们一起看看已经学习的同学对这本书的口碑和评价 ...

  9. python小项目实例流程-《Python编程:从入门到实践》DEMO实例代码

    这篇文章主要知识点是关于Python编程,从入门到实践,DEMO,,的内容,如果大家想对相关知识点有系统深入的学习,可以参阅以下电子书 前言 之前,项目后台基本都是使用 Java 的 SpringBo ...

  10. python网络爬虫教程-终于明了python网络爬虫从入门到实践

    Python是一款功能强大的脚本语言,具有丰富和强大的库,重要的是,它还具有很强的可读性,易用易学,非常适合编程初学者入门.以下是小编为你整理的python网络爬虫从入门到实践 环境配置:下载Pyth ...

最新文章

  1. WCF学习笔记(基于REST规则方式)
  2. Rust 数据类型介绍
  3. Oracle回应用户锁定,自治数据库是更好选择
  4. 《A Novel Pipeline Approach for Efficient Big Data Broadcasting》阅读报告
  5. java与java ee_CapeDwarf – Java EE上的Google App Engine
  6. openfire+elipse的导入配置
  7. 绝秘:在Excel中快速输入数据
  8. 大数据Hadoop学习记录(1)----HDFS目录和文件Shell操作
  9. LeetCode12 整数转罗马数字
  10. matlab:randn函数产生图像高斯噪声
  11. ArcGIS Pro中的回归分析浅析(下)地理加权回归工具(GWR)使用小结
  12. C++获取C盘临时文件夹的方法
  13. win7战网服务器修改,正在更新战网【设置办法】
  14. 【随笔记】做事要讲究轻重缓急,一定要把握主次轻重。
  15. 邮储银行计算机岗位笔试题,中国邮政储蓄银行各类岗位笔试经验汇总
  16. 2021年度济南职工医保门统定点医疗机构名单
  17. 第五章 系统方法---------基于业务驱动的企业安全架构(翻译,原作者John Sherwood)----仅学习使用
  18. 以标记清除的方式垃圾回收
  19. 毕设--自动浇花系统的设计
  20. php new object delete,DeleteObject()函数

热门文章

  1. python 流写入文件_python文件流操作
  2. ESTabBarController
  3. python 之 pip、pypdf2 安装与卸载
  4. Bruck:一个Web界面布局原型设计框架\n
  5. Mob之社会化分享集成ShareSDK
  6. VUE解决微信签名,SPA微信invalid signature问题,完美处理
  7. AngulerJS学习(五)按需动态载入文件
  8. git ingore添加忽略文件无较的解决方法
  9. VDI序曲二十三 制作OFFICE 2003应用程序虚拟化序列
  10. mysql数据库常用命令