几个入口汇总
原架构 Arch Design
协议说明 protocol spec
配置和接口说明 nsqd nsqlookupd nsqadmin
大部分基础功能和原版保持兼容, 使用方式上没有什么变动, 值得注意一下部分的改动
内部消息ID 使用16 字节存储, 但是具体的内容有所变动, 理论上外部客户端不依赖内部消息ID的具体内容, 因此标准的SDK可以兼容使用. 内部ID由原来的16字节的ascii hex string, 改变成了8字节的自增ID和8字节的跟踪ID.客户端的新功能和高级接口会使用跟踪ID的内容.
目前的延迟消息精度可能不准(最多可能和指定的延迟会达到相差十几秒), 另外延迟功能做了一定的加强, 支持最多一天的延后消费. 延后消费的消息不影响正常消费. 新版除了内存延迟外, 为了支持更多的延迟消息, 还支持磁盘延迟队列. 内部自动判断是否会进入磁盘延迟队列. 对于重试次数特别多, 或者延迟时间特别长的消息, 或者异常消息可能影响其他消息消费的消息, 都会进入到磁盘异常延迟队列. 在磁盘延迟队列的消息, 会以较低优先级的方式定时重新投递.
为了区分读写请求, 请求参数增加了读写查询区分, 生产者SDK都会传入写入请求标记, 消费者都会传读标记. 这些标记用于返回不同状态的数据节点(可以写入的节点和可以读取的节点区分开). 老的客户端由于不支持读写参数, 因此都是返回所有的可用的topic数据节点. nsqlookupd的返回信息也新增了分区的信息, 新版sdk会处理和分区相关的逻辑, 老版sdk依然解析老的响应数据. 对使用无影响.
很多命令增加了几种和集群变更相关的错误信息, 对业务使用没有什么影响, SDK内部会处理掉一些临时性的错误进行自动重试
E_FAILED_ON_NOT_LEADER
E_FAILED_ON_NOT_WRITABLE
E_TOPIC_NOT_EXIST
sdk层面的创建删除接口被移除, 因此老的sdk如果有尝试创建或者删除topic的行为将返回失败, 新版nsq只允许从nsqadmin和http接口去创建删除topic, 方便统一由运维管理.
新版改造后, 所有消息异步落盘, 同步复制到其他机器, 保障数据可靠性, 如果只是部分副本机器故障, 可以保障数据不丢失.
由于改造后只能leader节点读写, 为了提升性能, 引入分区概念, 每个分区可以独立的负责数据读写功能.
改造后的channel消费位置由cursor决定, 因此可以通过改变cursor的位置来改变消费位置, 移动到老的位置就可以消费历史数据. 具体可以参考运维指南
新的message id由内部id和跟踪id组成, 因此可以根据跟踪id关联到所有相关的消息及其状态, 改造后的NSQ支持针对某一个topic或者channel动态打开跟踪日志, 默认这些日志都是打印到本地, 方便出问题时进行排查消息状态. 为了跟方便搜索日志, 可以把日志导入到搜索系统进行搜索.
nsqadmin新增了如下数据
topic副本分布信息: 展示topic的每个分区的所有副本的分布情况, 以及同步状态.
生产方的统计数据包括: 写入延迟, 写入数据大小分布, 写入的producer连接信息
消费方的统计数据: 消费延迟分布情况, 延迟消息相关统计
集群排行榜统计数据: 统计集群内的top10超时量, 写入量, 重试量, 以及积压量, 方便快速的捞出可能异常的topic和channel.
-
客户端处理消息抛异常, 是否会丢消息?
不会, 服务端会重新推送没有确认的消息
-
客户端消息处理时间比较长如何处理超时?
客户端消费参数可以设置超时时间(msg_timeout), 默认是60s超时后服务端会重新推送消息, 如果业务处理比较耗时, 建议设置更长的msgtimeout时间
-
会不会有重复消费消息?
异常情况下, 可能会收到重复消息, 可能是生产方重复pub了消息, 也可能是服务端超时没有收到确认消费, 这些情况都会重新发送消息避免业务方丢失消息. 如果是偶发现象可以忽略.
-
生产方生产了消息, 消费方启动为什么收不到之前发的消息?
消费订阅关系未初始化之前, 生产的消息不会发到对应的channel上面, 只有channel创建之后, 订阅关系才算初始化, 之后的消息才能被对应的channel消费到. 初始化订阅关系后, 不管消费进程在不在, 都会推送消息到对应的channel里面.
-
是否会一直重试推送, 有最大重试次数吗?
服务端会重复推送直到收到确认消费包, 重试次数由客户端确定, 如果不想继续重试了, 就主动发送FIN包确认已经消费.(FIN请求极端网络下也会失败,等下次再消费)
-
某个客户端暂时不想处理消息了, 该如何操作?
可以通过SDK的接口发送ready=0给服务端, 之后就不会有新的消息推送过来, 要恢复推送, 再次发送ready>0即可
-
消息一下子推送太多处理不过来, 如何控制服务端给我推送少一点?
通过SDK的接口给服务端发送一个较小的ready值
-
为什么pub消息出现E_BAD_TOPIC?
topic名称不合法, 或者topic没有预先创建, 请找运维申请创建
-
为什么pub消息会出现E_TOPIC_NOT_EXIST?
集群没有创建该topic, 需要找运维申请创建
-
业务无法处理某些消息, 或者出现某些消息无法解析如何处理?
此时业务方应该记录日志并抛出异常, 服务端会重新推送让业务方重试, 业务方可以设置一个重试上限, 直到重试超过一定次数后, 才自动确认.
-
支持定时消息吗?
支持延后一段时间处理, 但是NSQ不支持精确的延时或者定时消息, 只支持稍后处理这种语意. 目前已经支持最多延迟一天处理.
-
为什么有时候在没有积压的情况下有较多的消费延迟
ready值是不是设置太小(建议值 工作线程数/分区数), max inflight是不是太小(建议值20~200之间, 至少2倍的并发工作线程数), 过小会导致服务端降低推送速度, 导致某些消息推送变慢.
-
是否支持设置自动跳过消费?
nsqadmin界面上可以操作skip channel, 针对channel自动跳过消费. 适用于某些情况下, 只需要在启动时进行消费, 停掉后不需要消费老的数据的情况下使用. 这样可以在下次启动前再unskip操作只消费最新的数据.
-
rdy值的建议配置
Rdy值一般调整成工作线程数/分区数比较合适, 保证每个工作线程有一个消息可以处理, 最大限度提高消费并发, 又不影响消费延迟, 如果消费处理能力较高, 也可以调整成和工作线程数一样. 如果业务消费支持批处理能力, 也可以设置成批处理的上限.