NSQ是Go语言编写的,开源的分布式消息队列中间件,其设计的目的是用来大规模地处理每天数以十亿计级别的消息。NSQ 具有分布式和去中心化拓扑结构,该结构具有无单点故障、故障容错、高可用性以及能够保证消息的可靠传递的特征,是一个成熟的、已在大规模生成环境下应用的产品。
单个nsqd实例可以用来树立多个数据流。
数据流也叫topic, 一个topic可以有多个channel。
每一个channel都接收该topic下面的所有消息,然后发送给消费者。channel会均匀的发送消息给消费者,不重复消费。
Topics and channels 都没有优先级,topic在两种情况下会被使用到,在发送数据到一该topic时候首次使用,或者有消费者订阅该topic下的某个channel时候。channel在有消费者订阅了该channle的时候使用。
这是一个辅助应用,启动目录服务保存着nsqd的地址,consumer可以通过nsqlookupd查询到它消费的channel、topic对应的nsqd服务。consumer不需要了解producer的信息。
提供了一个webUI,我们可以查询到topics/channels/consumers这些信息,便于监管。
nsq可以确保发送过来的消息至少被一个消费者消费;为了确保消息消费,重复消费是不可避免的。nsq通过以下来确保消息消费
安装: brew install nsq
使用(命令行):
在一个shell中:nsqlookupd
另一个shell中:nsqd –lookupd-tcp-address=127.0.0.1:4160
第三个shell中:nsqadmin –lookupd-http-address=127.0.0.1:4161
curl -d ‘hello world 1’ ‘http://127.0.0.1:4151/pub?topic=test’ //发送消息
nsq_to_file –topic=test –output-dir=/tmp –lookupd-http-address=127.0.0.1:4161
值得注意的是:nsq_to_file并不会精确的告诉topic产生的位置,它从nsqlookupd获取信息,不会丢掉消息。
go get github.com/nsqio/go-nsq
发送端
package main
import (
"github.com/nsqio/go-nsq"
)
var producer *nsq.Producer
func main() {
nsqd := "127.0.0.1:4150"
producer, err := nsq.NewProducer(nsqd, nsq.NewConfig())
producer.Publish("test", []byte("nihao")) //topic, message
if err != nil {
panic(err)
}
}
消费端
package main
import (
"fmt"
"sync"
"github.com/nsqio/go-nsq"
)
type NSQHandler struct {
}
func (this *NSQHandler) HandleMessage(msg *nsq.Message) error {
fmt.Println("receive", msg.NSQDAddress, "message:", string(msg.Body))
return nil
}
func testNSQ() {
waiter := sync.WaitGroup{}
waiter.Add(1)
go func() {
defer waiter.Done()
config:=nsq.NewConfig()
config.MaxInFlight=9
//建立多个连接
for i := 0; i<5; i++ {
consumer, err := nsq.NewConsumer("test", "zj", config) //topic, channel, config
if nil != err {
fmt.Println("err", err)
return
}
consumer.AddHandler(&NSQHandler{})
err = consumer.ConnectToNSQD("127.0.0.1:4150")
if nil != err {
fmt.Println("err", err)
return
}
}
select{}
}()
waiter.Wait()
}
func main() {
testNSQ();
}
Kafka自身服务与消息的生产和消费都依赖与Zookeeper,使用Scala语言开发。因为其消息的消费使用客户端Pull方式,消息可以被多个客户端消费,理论上消息会重复,但是不会丢失(除非消息过期)。因此比较常用的场景是作为日志传输的消息平台。
nsq默认是不保存消息,消息传递时候通常是无序的,可以保留信息去check时间戳,nsq更适合处理数据量大但是彼此间没有顺序关系的消息。
1.http://kuangjue.com/article/250
2.https://segmentfault.com/a/1190000009194607
3.https://blog.csdn.net/qq_26981997/article/details/56673522
4.https://nsq.io/overview/faq.html
break,default,func,interface,select,case,defer,go,map,struct,chan,else,goto,package,switch,const,fall,through,if,range,type,continue,for,import,return,var
// : 单行注释
/**/ : 多行注释
通过package来组织结构
只有package名称为main的包可以包含main函数
一个可执行程序有且只有一个main函数
通过import关键字来导入其他非main包
通过const关键字来进行常量的定义
通过在函数体外部使用var关键字来进行全局变量的声明与赋值
通过type关键字来进行结构(struct)或(interface)的声明
通过func关键字来进行函数的声明
逐个导入:
import "fmt"
import "os"
import "time"
统一导入
import (
"fmt"
"os"
"time"
)
导入包之后,就可以使用格式. 来对包中的函数进行调用
注意: 如果导入了包未被调用,则其中的函数或类型将会报出编译错误
在Go语言中通过大小写来决定该变量、常量、类型、接口、结构或函数是否可被外部所调用
根据约定,函数名首字母小写即为private, 大写即为public
当导入第三方包时,包名很可能非常接近或相同,需要使用别名来进行区别和调用如:
import std "fmt"
func main() {
std.Println("HelloWorld!");
}
省略调用如:
import . "fmt"
func main() {
Println("HelloWorld!");
}
省略调用的注意事项:不可与别名同时使用且不建议在实际项目中采用
注:以上附属简单学习资料来源于博客:https://blog.csdn.net/Tyro_java/article/details/76167601