-
安装Nsq
1.安装包管理器
go get github.com/tools/godep
2.安装依赖包
go get github.com/bmizerany/assert
3.安装Nsq
https://github.com/nsqio/nsq/releases
-
Producer
type Producer struct {
P *nsq.Producer
ip string
}
// 初始化生产者,最好是在项目初始化的时候就调用,否则可能会出现orm注册model冲突的情况
func InitProducer (addr string, mysql string) (wr *Producer) {
// 注册数据库
_, err := orm.GetDB("default_nsq")
if err != nil {
fmt.Println("orm.RegisterDataBase = ", mysql)
err = orm.RegisterDataBase("default_nsq", "mysql", mysql, 10, 10)
}
if err != nil {
panic("注册数据库失败:" + err.Error())
}
// 生产者配置,这里使用基本配置
cfg := nsq.NewConfig()
cfg.AuthSecret = "" // nsq认证密钥,暂时不需要
p, err := nsq.NewProducer(addr, cfg) // 新建一个生产者
if err != nil {
panic(err)
}
// 设置日志级别
p.SetLogger(log.New(os.Stdout, "nsq producer:", 0), nsq.LogLevelInfo)
wr = &Producer{P: p}
// 获取生产者ip
ip, err := getLocalIp()
if err != nil {
panic("nsq InitProducer:" + err.Error())
}
wr.ip = ip
return wr
}
func (p *Producer) Stop() {
p.P.Stop()
}
// 发布消息
func (p *Producer) Publish(topic string, body []byte) error {
// 不能发布空字节数组,否则会导致error
if len(body) == 0 {
return nil
}
go p.PublishLog(topic, uuid, body)
return p.P.Publish(topic, body)
}
// 添加日志 (需要编写models)
func (p *Producer) PublishLog(topic, uuid string, body []byte) (int64, error) {
log := &models.NsqPublishLog{}
log.Message = string(body)
log.NsqdUrl = p.P.String()
log.Topic = topic
log.ProducerIp = p.ip
log.MessageId = uuid
return models.AddNsqPublishLog(log)
}
-
Consumer
type HandlerRegist struct {
h nsq.Handler
topic string
channel string
nsqd string // address
ip string
}
// 初始化消费者 最好是在项目初始化的时候就调用,否则可能会出现orm注册model冲突的情况
func InitConsumer(rg *HandlerRegist, mysql string) *nsq.Consumer {
// 注册数据库
_, err := orm.GetDB("default_nsq")
if err != nil {
fmt.Println("orm.RegisterDataBase = ", mysql)
err = orm.RegisterDataBase("default_nsq", "mysql", mysql, 10, 10)
}
if err != nil {
panic("InitConsumer注册数据库失败:" + err.Error())
}
// 消费者配置,这里使用基本配置
cfg := nsq.NewConfig()
cfg.LookupdPollInterval = time.Second // 设置重连时间
cfg.AuthSecret = "" // nsq认证密钥,暂时不需要
c, err := nsq.NewConsumer(rg.topic, rg.channel, cfg) // 新建一个消费者
if err != nil {
panic(err)
}
// 设置日志级别
c.SetLogger(log.New(os.Stdout, "nsq consumer:", 0), nsq.LogLevelInfo)
// 获取消费者ip
ip, err := getLocalIp()
if err != nil {
panic("nsq NewNsqConsumer:" + err.Error())
}
rg.ip = ip
// 添加消费者接口
c.AddHandler(rg)
// 建立一个nsqd连接
if err := c.ConnectToNSQD(rg.nsqd); err != nil {
panic(err)
}
// 建立多个nsqd连接
if err := c.ConnectToNSQDs([]string{"address1", "address2"}); err != nil {
panic(err)
}
// 建立NSQLookupd连接
if err := c.ConnectToNSQLookupd(rg.nsqd); err != nil {
panic(err)
}
return c
}
// c.Stop()
// 处理消息
func (rg *HandlerRegist) HandleMessage(message *nsq.Message) error {
go rg.ConsumeLog(message)
return rg.h.HandleMessage(message)
}
// 添加日志 (需要编写models)
func (rg *HandlerRegist) ConsumeLog(message *nsq.Message) (int64, error) {
log := &models.NsqConsumeLog{}
log.ConsumerIp = rg.ip
log.NsqdUrl = rg.nsqd
log.Topic = rg.topic
log.Channel = rg.channel
log.Message = string(message.Body)
log.MessageId = getMessageId(message.Body)
return models.AddNsqConsumeLog(log)
}
func getMessageId(body []byte) string {
m := map[string]interface{}{}
json.Unmarshal(body, &m)
if v, ok := m["nsq_msg_uuid"].(string); ok {
return v
}
return ""
}
-
IP
func getLocalIp() (string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
fmt.Println("获取ip地址失败")
return "", err
}
var ip []string
for _, address := range addrs {
// 检查ip地址判断是否回环地址
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
ip = append(ip, ipnet.IP.String())
}
}
}
return strings.Join(ip, ";"), nil
}