zoukankan      html  css  js  c++  java
  • GO与Rabbitmq相关

    Rabitmq的环境搭建

    定义和特征

    • RabbitMQ是面向消息的中间件,用于组件之间的解耦,主要体现在消息的发送者和消费者之间的强依赖问题。
    • RabbitMQ特点:高可用,扩展性,多语言客户端,管理界面等
    • RabbitMQ使用场景:流量削峰,异步处理,应用解耦等

    安装命令

    • 安装erlang:
      #由于RabbitMQ采用Erlang语言编写,所以先安装Erlang
      sudo apt-get install erlang-nox
      
      #如果在安装过程中报错:ubuntu18.04 E: dpkg 被中断,您必须手工运行 ‘sudo dpkg –configure -a’ 解决此问题。如果使用之后不行,那么删除掉然后重建即可。sudo rm /var/lib/dpkg/updates/*
      
      #安装RabbitMQ
      sudo apt-get update
      sudo apt-get upgrade
      sudo apt-get install rabbitmq-server
      
      # 查看运行状态
      systemctl status rabbitmq-server   #Active: active (running) 说明处于运行状态
      # service rabbitmq-server status 用service指令也可以查看,同systemctl指令
      
      #启动、停止、重启
      service rabbitmq-server start    # 启动
      service rabbitmq-server stop     # 停止
      service rabbitmq-server restart  # 重启 
      
      #web界面
      rabbitmq-plugins enable rabbitmq_management   # 启用插件
      service rabbitmq-server restart    # 重启
      
    • 运行后,可以访问http://localhost:15672, 并使用默认密码:guest/guest进入管理界

       更对多rabbitmq资料:https://blog.csdn.net/vrg000/article/details/81165030

    RabbitMQ命令管理

    • rabbitmq-plugins list : 列出当前rabbitMQ可以使用的插件
    • rabbitmq-plugins enable/disable rabbitmq_management  : 启动/关闭相应的插件

    RabbitMQ核心概念

    • VirtualHost:在web页面中的"Admin"页中,点击"Virtual host", 再点击"Add new virtual host",填写一个名称后,会多出一个虚拟host
    • 通过添加用户,然后将虚拟host绑定到特定的用户
    • 虚拟host,起到了数据隔离的作用,指定用户只能在对应的host上访问
    • 当一个用户可以使用多个虚拟host时,对应的exchanges也很很多,这样我们可以隔离我们的开发环境

      

    • Exchanges:交换机,相当于路由的中转站,生产者生产好数据后会首先通过它访问的路径找到对应RabbitMQ的key,并发送到其中
    • Queues:  用来绑定我们的交换机,接受我们的消息,只要没有消费者就一直存在队列中
    • Binding:  将队列绑定到对应的交换机上,不同的绑定形式,可以实现不同的工作模式

    6种工作模式

    •  Simple模式:

      

     代码实现:

     首先我们需要设置GOPATH路径,同时设置全局的代理:在~/.bashrc中添加如下内容,然后source  .bashrc

    export PATH=$PATH:/usr/local/go/bin
    export GOPATH=/home/wangli/桌面/Go_code
    export GOPROXY=https://goproxy.cn,direct
    

      创建一个项目,进入项目目录后,在终端中输入:go mod init demo  (demo)随意起名字,里面可以会自动监听我们使用的所有包,我们只需要使用demo/xxx导入包就可以了

    (Goland中可以通过go Moudle来创建)

    go-mod相关

      Go现在通过 go.mod 文件来配置模块加载使用是非常方便了,下面说下如何在当前项目中加载另一个本地正在开发的模块:

    1、便捷一:默认使用 github.com/zhouzme/snail-go 包会到 github 上去下载,但这个包还在本地开发中并未push到线上,那么可以通过 replace 配置来重定向当前项目对该包的加载路径:replace github.com/zhouzme/snail-go => E:Gosnail-go  。
        这里 E:Gosnail-go 为本地包的绝对路径,这样写就可以了,当本地snail-go包代码修改后就可以在当前项目看到实时效果了,注意中间符号是 =>
    
    2、便捷二:go mod  init mygo   (这里mygo名字也可以叫其他名字,一般为了与项目名称对应,就用项目名字)
    项目目录下会生成go.mod文件, 类似于python的requirements.txt文件。同时也生成一个go.sum文件,主要记载了下载包的哈希值用于校验,我们用不到。
    
    3、便捷三:go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。  go toolchain会在各类命令执行时,比如执行go get、go build、go run、go mod等命令时,自动修改和维护go.mod文件,这点跟pip还是有区别的
    

       go.mod中提供了以下各类命令

    1、module 语句指定包的名字(路径)
    2、require 语句指定的依赖项模块
    3、replace 语句可以替换依赖项模块
    4、exclude 语句可以忽略依赖项模块
    

       go.mod由于某些已知的原因,并不是所有的package都能成功下载,比如:golang.org下的包。            可以在 go.mod 文件中使用 replace 指令替换成github上对应的库,来下载相应的包。比如:

    replace (
        golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 => github.com/golang/cryptov0.0.0-20190701094942-4def268fd1a4
     )
    
    或者: 
    replace golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 => github.com/golang/crypto v0.0.0-20190701094942-4def268fd1a4
    

       go.mod相关使用命令

    1. go mod init 
    初始化一个go.mod文件到当前目录, 实际上是创建了一个以当前目录为模块的mod。
    
    2.go mod tidy
    类似maven update, 通过这个命令下载项目依赖的第三方库,同时会去掉不相关的库。
    
     3.go mod vender
    把第三方的库拷贝到当前目录的vendor目录
    
    4.go mod verify
    检查下载的第三方库有没有本地修改,如果有修改,则会返回非0,否则验证成功。
    

     项目代码

    • RabbitMQ/rabbitmq.go
      package RabbitMQ
      
      import (
      	"fmt"
      	"github.com/streadway/amqp"
      	"log"
      )
      
      // 创建连接url
      const MQURL = "amqp://admin:admin@127.0.0.1:5672/test"
      
      type RabbitMQ struct {
      	conn    *amqp.Connection
      	channel *amqp.Channel
      
      	// 队列名称
      	QueueName string
      	// 交换机
      	Exchange string
      	// key
      	Key string
      	// 连接信息
      	Mqurl string
      }
      
      // 创建连接实例
      func NewRabbitMQ(queueName string, exchange string, key string) *RabbitMQ {
      	// exchange 为空会使用默认的default
      	rabbitmq := &RabbitMQ{QueueName: queueName, Exchange: exchange, Key: key, Mqurl: MQURL}
      	var err error
      	// 创建rabbitmq来连接
      	rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
      	rabbitmq.failOnErr(err, "创建连接错误!")
      
      	// 创建channel
      	rabbitmq.channel, err = rabbitmq.conn.Channel()
      	rabbitmq.failOnErr(err, "获取channel失败")
      	return rabbitmq
      }
      
      // 断开连接:channel和conn
      func (r *RabbitMQ) Destory() {
      	r.channel.Close()
      	r.conn.Close()
      }
      
      // 错误处理的函数
      func (r *RabbitMQ) failOnErr(err error, message string) {
      	if err != nil {
      		log.Fatalf("%s: %s", message, err)
      		panic(fmt.Sprintf("%s", message))
      	}
      }
      
      // step1: simple style 创建简单模式的实例, 只需要队列名
      func NewRabbitMQSimple(queueName string) *RabbitMQ {
      	return NewRabbitMQ(queueName, "", "")
      }
      
      // step2: 简单模式下生产
      func (r *RabbitMQ) PublishSimple(message string) {
      	// 固定用法  申请队列,如果队列不存在会自动创建,如果存在则直接使用,保证队列中能存入数据
      	_, err := r.channel.QueueDeclare(
      		r.QueueName, // 队列名
      		false,       // 控制是否持久化
      		false,       // 是否自动删除,当最后一个消费者断开连接后是否删除
      		false,       // 是否具有排他性,其他用户不可访问
      		false,       // 是否阻塞
      		nil,         //  额外属性
      	)
      	if err != nil {
      		fmt.Println(err)
      	}
      
      	// 发送消息到队列中
      	r.channel.Publish(
      		r.Exchange,
      		r.QueueName,
      		false, // mandatory 如果为true,会根据exchange类型和routkey规则,如果无法找到符合条件的队列那么会把消息返回给发送者
      		false, // immediate 如果为true,当exchange发送消息到队列后发现队列没有绑定消费者后会把消息返回
      		amqp.Publishing{
      			ContentType: "text/plain",
      			Body:        []byte(message),
      		})
      }
      
      // 简单模式的消费消息
      func (r *RabbitMQ) ConsumeSimple() {
      	// 固定用法  申请队列,如果队列不存在会自动创建,如果存在则直接使用,保证队列中能存入数据
      	_, err := r.channel.QueueDeclare(
      		r.QueueName, // 队列名
      		false,       // 控制是否持久化
      		false,       // 是否自动删除,当最后一个消费者断开连接后是否删除
      		false,       // 是否具有排他性,其他用户不可访问
      		false,       // 是否阻塞
      		nil,         //  额外属性
      	)
      	if err != nil {
      		fmt.Println(err)
      	}
      
      	// 接受消息
      	msgs, err := r.channel.Consume(
      			r.QueueName,
      			"",     // 用来区分多个消费在
      			true,   // 是否自动应答, 主动的告诉mq自己已经消费完了,如果false,需要回调函数
      			false,  // 是否排他性
      			false,  // 如果设置为true, 表示不能将同一个connection中发送的消息传递给这个connect中的消费者
      			false,  // 设置为阻塞,一个一个消费
      			nil,    // 附加信息
      		)
      	if err != nil {
      		fmt.Println(err)
      	}
      
      	// 消费时的固定写法,用来阻塞
      	forever := make(chan bool)
      	// 启用协程处理消息
      	go func() {
      		for d := range msgs {
      			// 实现我们要处理的逻辑函数
      			log.Printf("Received a message: %s", d.Body)
      		}
      	}()
      
      	log.Printf("[*] Waiting for message,To exit press CTRL + C")
      	<- forever
      }
      
    • mainSimplePublish.go
      package main
      
      import (
      	"demo/RabbitMQ"
      	"fmt"
      )
      
      func main() {
      	rabbitmq := RabbitMQ.NewRabbitMQSimple("testSimple")
      	rabbitmq.PublishSimple("Hello Test! ")
      	fmt.Println("发送成功!")
      }
      
    • mainSimpleRecieve.go
      package main
      
      import (
      	"demo/RabbitMQ"
      )
      
      func main() {
      	rabbitmq := RabbitMQ.NewRabbitMQSimple("testSimple")
      	rabbitmq.ConsumeSimple()
      }
      

      运行后可以查看web界面的使用图

  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/double-W/p/12586258.html
Copyright © 2011-2022 走看看