Nsq消息队列

  • 安装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
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值