go实现NSQ消息队列的集群部署

2024-03-19 07:08

本文主要是介绍go实现NSQ消息队列的集群部署,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 安装

官方下载页面根据自己的平台下载并解压即可。
我安装的是windows版本的
在这里插入图片描述
2 NSQ的工作模式
每个nsqd实例旨在一次处理多个数据流。这些数据流称为“topics”,一个topic具有1个或多个“channels”。每个channel都会收到topic所有消息的副本,实际上下游的服务是通过对应的channel来消费topic消息。

topic和channel不是预先配置的。topic在首次使用时创建,方法是将其发布到指定topic,或者订阅指定topic上的channel。channel是通过订阅指定的channel在第一次使用时创建的。

topic和channel都相互独立地缓冲数据,防止缓慢的消费者导致其他chennel的积压(同样适用于topic级别)。
在这里插入图片描述

3 集群部署

启动的exe文件均在下载目录bin下

  • 启动nsqlookupd
nsqlookupd.exe

nsqlookupd监听的是4160 4161对应tcp http端口

  • 启动3个nsqd
    我这里启动了三个nsqd,记得在.bin/datas下建立三个node目录,
    在这里插入图片描述
    如果启动单个测试,参考博客

一个端口就对应一个nsqd
第一个nsqd就算监听4150 4151端口的

nsqd.exe --lookupd-tcp-address 127.0.0.1:4160 --broadcast-address 127.0.0.1 --data-path=./datas/node1 -http-address 127.0.0.1:4151 -tcp-address 127.0.0.1:4150
nsqd.exe --lookupd-tcp-address 127.0.0.1:4160 --broadcast-address 127.0.0.1 --data-path=./datas/node2 -http-address 127.0.0.1:4251 -tcp-address 127.0.0.1:4250
nsqd.exe --lookupd-tcp-address 127.0.0.1:4160 --broadcast-address 127.0.0.1 --data-path=./datas/node3 -http-address 127.0.0.1:4351 -tcp-address 127.0.0.1:4350

测试代码

总共有四个生产者

  • 第1个生产者发给端口4150 topic == "topic_demo11"的nsqd
  • 第2个生产者发给端口4150 topic == "topic_demo12"的nsqd
  • 第3个生产者发给端口4250 topic == "topic_demo11"的nsqd
  • 第4个生产者发给端口4350 topic == "topic_demo11"的nsqd

生产者代码

// nsq_producer/main.go
package mainimport ("fmt""sync""time""github.com/nsqio/go-nsq"
)// NSQ Producer Demovar producer *nsq.Producervar wg sync.WaitGroup
var mutex sync.Mutex
var k int64// 初始化生产者
func initProducer(str string) (err error) {config := nsq.NewConfig()producer, err = nsq.NewProducer(str, config)if err != nil {fmt.Printf("create producer failed, err:%v\n", err)return err}return nil
}//向指定ip port topic生产数据
func producerSendsData(ip string, port int, topic string) {//生产者往4150的nsqd上的dtopic_demo发信息nsqAddress := fmt.Sprintf("%s:%d", ip, port)//fmt.Println(nsqAddress)//一个端口就对应一个nsqderr := initProducer(nsqAddress)if err != nil {fmt.Printf("init producer failed, err:%v\n", err)return}for i := 0; i < 20; i++ {mutex.Lock()data := fmt.Sprintf("生产者发的数据:%d", k)// 向 'topic_demo' publish 数据err = producer.Publish(topic, []byte(data))if err != nil {fmt.Printf("publish msg to nsq failed, err:%v\n", err)continue}mutex.Unlock()k += 1//time.Sleep(time.Second)time.Sleep(time.Microsecond * 200)fmt.Println(data, nsqAddress)}defer wg.Done()
}
func main() {k = 0ip := "127.0.0.1"wg.Add(4)//一个端口就对应一个nsqd//第一个nsqd 端口4150 topic := "topic_demo"port1 := 4150topic11 := "topic_demo11"go producerSendsData(ip, port1, topic11)//第一个nsqd 端口4150 topic02 := "topic_demo02"topic12 := "topic_demo12"go producerSendsData(ip, port1, topic12)//第2个nsqd 端口4250 topic := "topic_demo11"//第2个nsqd我同样向topic_demo11中传输数据port2 := 4250topic21 := "topic_demo11" //"topic_demo21"go producerSendsData(ip, port2, topic21)//第3个nsqd 端口4350 topic02 := "topic_demo02"port3 := 4350topic31 := "topic_demo11"go producerSendsData(ip, port3, topic31)wg.Wait()//这部分代码是从标准输入读取了发送的/*reader := bufio.NewReader(os.Stdin) // 从标准输入读取for {data, err := reader.ReadString('\n')if err != nil {fmt.Printf("read string from stdin failed, err:%v\n", err)continue}data = strings.TrimSpace(data)if strings.ToUpper(data) == "Q" { // 输入Q退出break}// 向 'topic_demo' publish 数据err = producer.Publish("topic_demo", []byte(data))if err != nil {fmt.Printf("publish msg to nsq failed, err:%v\n", err)continue}}*/
}

总共有2个消费者

  • 第一个消费者去收topic==topic_demo11的数据
  • 第一个消费者去收topic==topic_demo12的数据

消费者代码

package mainimport ("fmt""os""os/signal""sync""syscall""time""github.com/nsqio/go-nsq"
)// NSQ Consumer Demo
var wg sync.WaitGroup// MyHandler 是一个消费者类型
type MyHandler struct {Title string
}// HandleMessage 是需要实现的处理消息的方法
func (m *MyHandler) HandleMessage(msg *nsq.Message) (err error) {fmt.Printf("%s recv from %v, msg:%v\n", m.Title, msg.NSQDAddress, string(msg.Body))return
}// 初始化消费者
func initConsumer(topic string, channel string, address string) {config := nsq.NewConfig()config.LookupdPollInterval = 15 * time.Secondc, err := nsq.NewConsumer(topic, channel, config)if err != nil {fmt.Printf("create consumer failed, err:%v\n", err)return}consumer := &MyHandler{Title: topic + " " + channel,}c.AddHandler(consumer)// if err := c.ConnectToNSQD(address); err != nil { // 直接连NSQDif err := c.ConnectToNSQLookupd(address); err != nil { // 通过lookupd查询fmt.Printf("c.ConnectToNSQLookupd(address) failed, err:%v\n", err)return}//time.Sleep(time.Second)defer wg.Done()}func main() {wg.Add(2)//topic_demo就是topic second是channel//第一个nsqd 端口4150 topic := "topic_demo11"下的数据用两个消费者(first和second)消费go initConsumer("topic_demo11", "first", "127.0.0.1:4161")go initConsumer("topic_demo12", "first", "127.0.0.1:4161")// //第一个nsqd 端口4150 topic02 := "topic_demo02"下的数据用1个消费者(first)消费// go initConsumer("topic_demo12", "first", "127.0.0.1:4161")// //第2个nsqd 端口4250 topic := "topic_demo21"// go initConsumer("topic_demo21", "second", "127.0.0.1:4161")wg.Wait()c := make(chan os.Signal)        // 定义一个信号的通道signal.Notify(c, syscall.SIGINT) // 转发键盘中断信号到c<-c                              // 阻塞
}

测试结果演示

4个生产者总共发送了80个数据,2个消费者也接收到了80个数据
在这里插入图片描述

这篇关于go实现NSQ消息队列的集群部署的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/825180

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque