初始化项目
This commit is contained in:
16
trunk/framework/mqMgr/config.go
Normal file
16
trunk/framework/mqMgr/config.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package mqMgr
|
||||
|
||||
// 消息队列配置对象
|
||||
type QueueConfig struct {
|
||||
// 地域
|
||||
Region string
|
||||
|
||||
// 队列名称
|
||||
QueueName string
|
||||
|
||||
// API密钥Id
|
||||
SecretId string
|
||||
|
||||
// API密钥key
|
||||
SecretKey string
|
||||
}
|
||||
109
trunk/framework/mqMgr/model/common_request.go
Normal file
109
trunk/framework/mqMgr/model/common_request.go
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
请求结构简介
|
||||
最近更新时间:2019-08-01 19:14:44
|
||||
|
||||
编辑 查看pdf
|
||||
在这篇文章中:
|
||||
服务地址
|
||||
通信协议
|
||||
请求方法
|
||||
请求参数
|
||||
字符编码
|
||||
对腾讯云的 API 接口的调用是通过向腾讯云 API 的服务端地址发送请求,并按照接口说明在请求中加入相应的请求参数来完成的。腾讯云 API 的请求结构由:服务地址、通信协议、请求方法、请求参数和字符编码组成。具体描述如下:
|
||||
|
||||
服务地址
|
||||
腾讯云 API 的服务接入地址与具体模块相关,详细请参见各接口相关描述。
|
||||
|
||||
通信协议
|
||||
腾讯云 API 的大部分接口都通过 HTTPS 进行通信,为您提供高安全性的通信通道。
|
||||
|
||||
请求方法
|
||||
腾讯云 API 同时支持 POST 和 GET 请求。
|
||||
|
||||
注意:
|
||||
|
||||
POST 和 GET 请求不能混合使用,若使用 GET 方式,则参数均从 Querystring 取得;
|
||||
若使用 POST 方式,则参数均从 Request Body 中取得,而 Querystring 中的参数将忽略。
|
||||
两种请求方式的参数格式规则相同,一般情况下使用 GET 请求,当参数字符串过长时推荐使用 POST。
|
||||
如果用户的请求方法是 GET,则对所有请求参数值均需要做 URL 编码,若为 POST,则无需对参数编码。
|
||||
GET 请求的最大长度根据不同的浏览器和服务器设置有所不同,例如,传统 IE 浏览器限制为 2K,Firefox 限制为 8K;对于一些参数较多、长度较长的 API 请求,建议您使用 POST 方法以免在请求过程中会由于字符串超过最大长度而导致请求失败。
|
||||
对于 POST 请求,您需要使用 x-www-form-urlencoded 的形式传参,因为云 API 侧是从 $_POST 中取出请求参数的。
|
||||
请求参数
|
||||
腾讯云 API 的每个请求都需要指定两类参数:公共请求参数以及接口请求参数。其中公共请求参数是每个接口都要用到的请求参数,具体可参见 公共请求参数,而接口请求参数是各个接口所特有的,具体见各个接口的“请求参数”描述。
|
||||
|
||||
字符编码
|
||||
腾讯云 API 的请求及返回结果均使用 UTF-8 字符集进行编码。
|
||||
*/
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"goutil/mathUtil"
|
||||
)
|
||||
|
||||
// CommonRequest 公共请求参数对象
|
||||
type CommonRequest struct {
|
||||
// Action 指令接口名称(必须)
|
||||
Action string
|
||||
|
||||
// 地域参数(必须)
|
||||
Region string
|
||||
|
||||
// Timestamp 当前UNIX时间戳(必须)
|
||||
Timestamp uint64
|
||||
|
||||
// Nonce 随机正整数(必须)
|
||||
Nonce uint32
|
||||
|
||||
// SecretId 在云API密钥上申请的标识身份的SecretId(必须)
|
||||
SecretId string
|
||||
|
||||
// 请求签名,用来验证此次请求的合法性,需要用户根据实际的输入参数计算得出。
|
||||
Signature string
|
||||
|
||||
// 签名方式,目前支持 HmacSHA256 和 HmacSHA1。只有指定此参数为 HmacSHA256 时,才使用 HmacSHA256 算法验证签名,其他情况均使用 HmacSHA1 验证签名。
|
||||
SignatureMethod string
|
||||
|
||||
// 队列名称(此属性虽然不是API文档中的公共属性,但是在队列模型中确实事实上的公共属性,所以将其转移到此处)
|
||||
queueName string
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装请求参数字典
|
||||
// 返回值
|
||||
// map[string]interface{}:请求参数字
|
||||
func (this *CommonRequest) AssembleParamMap() map[string]string {
|
||||
result := make(map[string]string)
|
||||
|
||||
// 组装参数
|
||||
result["Action"] = this.Action
|
||||
result["Region"] = this.Region
|
||||
result["Timestamp"] = fmt.Sprintf("%d", this.Timestamp)
|
||||
result["Nonce"] = fmt.Sprintf("%d", this.Nonce)
|
||||
result["SecretId"] = this.SecretId
|
||||
result["SignatureMethod"] = this.SignatureMethod
|
||||
result["queueName"] = this.queueName
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// NewCommonRequest 新建公共请求参数对象
|
||||
// 参数
|
||||
// action:指令接口名称
|
||||
// region:地域
|
||||
// secretId:在云API密钥上申请的标识身份的SecretId
|
||||
// queueName:队列名称
|
||||
// 返回值
|
||||
// *CommonRequest:公共请求参数对象
|
||||
func NewCommonRequest(action, region, secretId, queueName string) *CommonRequest {
|
||||
return &CommonRequest{
|
||||
Action: action,
|
||||
Region: region,
|
||||
Timestamp: uint64(time.Now().Unix()),
|
||||
Nonce: mathUtil.GetRand().Uint32(),
|
||||
SecretId: secretId,
|
||||
SignatureMethod: "HmacSHA256",
|
||||
queueName: queueName,
|
||||
}
|
||||
}
|
||||
28
trunk/framework/mqMgr/model/common_response.go
Normal file
28
trunk/framework/mqMgr/model/common_response.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
// CommonResponse 公共请求结果对象
|
||||
type CommonResponse struct {
|
||||
// 错误码
|
||||
Code ResultStatus `json:"code"`
|
||||
|
||||
// 错误提示信息
|
||||
Message string `json:"message"`
|
||||
|
||||
// 服务器生成的请求Id
|
||||
RequestId string `json:"requestId"`
|
||||
}
|
||||
|
||||
// IsSuccess 请求结果是否成功
|
||||
func (this *CommonResponse) IsSuccess() bool {
|
||||
return this.Code == Success
|
||||
}
|
||||
|
||||
// IsFailure 请求结果是否失败
|
||||
func (this *CommonResponse) IsFailure() bool {
|
||||
return this.Code != Success
|
||||
}
|
||||
|
||||
// HasMessage 请求结果是否有信息
|
||||
func (this *CommonResponse) HaveNoMessage() bool {
|
||||
return this.Code == NoMessage
|
||||
}
|
||||
13
trunk/framework/mqMgr/model/errorInfo.go
Normal file
13
trunk/framework/mqMgr/model/errorInfo.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package model
|
||||
|
||||
// 错误信息对象
|
||||
type ErrorInfo struct {
|
||||
// 错误码
|
||||
Code int `json:"code"`
|
||||
|
||||
// 错误提示信息
|
||||
Message string `json:"message"`
|
||||
|
||||
// 对应删除失败的消息句柄
|
||||
ReceiptHandle string `json:"receiptHandle"`
|
||||
}
|
||||
13
trunk/framework/mqMgr/model/irequest.go
Normal file
13
trunk/framework/mqMgr/model/irequest.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package model
|
||||
|
||||
// IRequest 请求对象接口
|
||||
type IRequest interface {
|
||||
// GetActionName 获取方法名
|
||||
GetActionName() string
|
||||
|
||||
// SetCommonRequestObject 设置公共请求对象
|
||||
SetCommonRequest(*CommonRequest)
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
AssembleParamMap() map[string]string
|
||||
}
|
||||
25
trunk/framework/mqMgr/model/messageInfo.go
Normal file
25
trunk/framework/mqMgr/model/messageInfo.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package model
|
||||
|
||||
// 消息对象
|
||||
type MessageInfo struct {
|
||||
// 本次消费的消息正文
|
||||
MsgBody string `json:"msgBody"`
|
||||
|
||||
// 服务器生成消息的唯一标识Id
|
||||
MsgId string `json:"msgId"`
|
||||
|
||||
// 每次消费返回唯一的消息句柄。用于删除该消息,仅上一次消费时产生的消息句柄能用于删除消息。
|
||||
ReceiptHandle string `json:"receiptHandle"`
|
||||
|
||||
// 消费被生产出来,进入队列的时间
|
||||
EnqueueTime int64 `json:"enqueueTime"`
|
||||
|
||||
// 第一次消费该消息的时间
|
||||
FirstDequeueTime int64 `json:"firstDequeueTime"`
|
||||
|
||||
// 消息的下次可见(可再次被消费)时间
|
||||
NextVisibleTime int64 `json:"nextVisibleTime"`
|
||||
|
||||
// 消息被消费的次数
|
||||
DequeueCount int64 `json:"dequeueCount"`
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 批量删除消息请求对象
|
||||
type BatchDeleteMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 上次消费消息时返回的消息句柄列表
|
||||
receiptHandleList []string
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *BatchDeleteMessageRequest) GetActionName() string {
|
||||
return "BatchDeleteMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequestObject 设置公共请求对象
|
||||
func (this *BatchDeleteMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *BatchDeleteMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
for index, msg := range this.receiptHandleList {
|
||||
key := fmt.Sprintf("receiptHandle.%d", index)
|
||||
paramMap[key] = msg
|
||||
}
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewBatchDeleteMessageRequest(receiptHandleList []string) *BatchDeleteMessageRequest {
|
||||
return &BatchDeleteMessageRequest{
|
||||
receiptHandleList: receiptHandleList,
|
||||
}
|
||||
}
|
||||
|
||||
// 批量删除消息请求返回结果对象
|
||||
type BatchDeleteMessageResponse struct {
|
||||
*CommonResponse
|
||||
|
||||
// 无法成功删除的错误列表
|
||||
ErrorList []*ErrorInfo `json:"errorList"`
|
||||
}
|
||||
|
||||
func NewBatchDeleteMessageResponse() *BatchDeleteMessageResponse {
|
||||
return &BatchDeleteMessageResponse{}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 批量消费消息请求对象
|
||||
type BatchReceiveMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 本次消费的消息数量。取值范围 1-16。(必须)
|
||||
numOfMsg int
|
||||
|
||||
// 本次请求的长轮询等待时间(非必须)
|
||||
pollingWaitSeconds int
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *BatchReceiveMessageRequest) GetActionName() string {
|
||||
return "BatchReceiveMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequest 设置公共请求对象
|
||||
func (this *BatchReceiveMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *BatchReceiveMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
paramMap["numOfMsg"] = fmt.Sprintf("%d", this.numOfMsg)
|
||||
paramMap["pollingWaitSeconds"] = fmt.Sprintf("%d", this.pollingWaitSeconds)
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewBatchReceiveMessageRequest(numOfMsg, pollingWaitSeconds int) *BatchReceiveMessageRequest {
|
||||
return &BatchReceiveMessageRequest{
|
||||
numOfMsg: numOfMsg,
|
||||
pollingWaitSeconds: pollingWaitSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
// 批量消费消息请求返回结果对象
|
||||
type BatchReceiveMessageResponse struct {
|
||||
*CommonResponse
|
||||
|
||||
// message信息列表
|
||||
MsgInfoList []*MessageInfo `json:"msgInfoList"`
|
||||
}
|
||||
|
||||
func NewBatchReceiveMessageResponse() *BatchReceiveMessageResponse {
|
||||
return &BatchReceiveMessageResponse{}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 批量发送消息请求对象
|
||||
type BatchSendMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 消息正文列表
|
||||
msgBodyList []string
|
||||
|
||||
// 单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
|
||||
delaySeconds int
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *BatchSendMessageRequest) GetActionName() string {
|
||||
return "BatchSendMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequest 设置公共请求对象
|
||||
func (this *BatchSendMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *BatchSendMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
for index, msg := range this.msgBodyList {
|
||||
key := fmt.Sprintf("msgBody.%d", index)
|
||||
paramMap[key] = msg
|
||||
}
|
||||
paramMap["delaySeconds"] = fmt.Sprintf("%d", this.delaySeconds)
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewBatchSendMessageRequest(msgBodyList []string, delaySeconds int) *BatchSendMessageRequest {
|
||||
return &BatchSendMessageRequest{
|
||||
msgBodyList: msgBodyList,
|
||||
delaySeconds: delaySeconds,
|
||||
}
|
||||
}
|
||||
|
||||
// 批量发送消息请求返回结果对象
|
||||
type BatchSendMessageResponse struct {
|
||||
*CommonResponse
|
||||
|
||||
// message信息列表
|
||||
MsgInfoList []*MessageInfo `json:"msgInfoList"`
|
||||
}
|
||||
|
||||
func NewBatchSendMessageResponse() *BatchSendMessageResponse {
|
||||
return &BatchSendMessageResponse{}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package model
|
||||
|
||||
// 删除消息请求对象l
|
||||
type DeleteMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 上次消费返回唯一的消息句柄,用于删除消息。(必须)
|
||||
receiptHandle string
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *DeleteMessageRequest) GetActionName() string {
|
||||
return "DeleteMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequest 设置公共请求对象
|
||||
func (this *DeleteMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *DeleteMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
paramMap["receiptHandle"] = this.receiptHandle
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewDeleteMessageRequest(receiptHandle string) *DeleteMessageRequest {
|
||||
return &DeleteMessageRequest{
|
||||
receiptHandle: receiptHandle,
|
||||
}
|
||||
}
|
||||
|
||||
// 删除消息请求返回结果对象
|
||||
type DeleteMessageResponse struct {
|
||||
// 公共请求结果
|
||||
*CommonResponse
|
||||
}
|
||||
|
||||
func NewDeleteMessageResponse() *DeleteMessageResponse {
|
||||
return &DeleteMessageResponse{}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package model
|
||||
|
||||
// 消费消息请求对象
|
||||
type GetQueueAttributesRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *GetQueueAttributesRequest) GetActionName() string {
|
||||
return "GetQueueAttributes"
|
||||
}
|
||||
|
||||
// SetCommonRequestObject 设置公共请求对象
|
||||
func (this *GetQueueAttributesRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *GetQueueAttributesRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewGetQueueAttributesRequest() *GetQueueAttributesRequest {
|
||||
return &GetQueueAttributesRequest{}
|
||||
}
|
||||
|
||||
// 消费消息请求返回结果对象
|
||||
type GetQueueAttributesResponse struct {
|
||||
*CommonResponse
|
||||
|
||||
MaxMsgHeapNum int `json:"maxMsgHeapNum"` // 最大堆积消息数。取值范围在公测期间为 1,000,000 - 10,000,000,正式上线后范围可达到 1000,000-1000,000,000。默认取值在公测期间为 10,000,000,正式上线后为 100,000,000。
|
||||
PollingWaitSeconds int `json:"pollingWaitSeconds"` // 消息接收长轮询等待时间。取值范围0 - 30秒,默认值0。
|
||||
VisibilityTimeout int `json:"visibilityTimeout"` // 消息可见性超时。取值范围1 - 43200秒(即12小时内),默认值30。
|
||||
MaxMsgSize int `json:"maxMsgSize"` // 消息最大长度。取值范围1024 - 1048576 Byte(即1K - 1024K),默认值65536。
|
||||
MsgRetentionSeconds int `json:"msgRetentionSeconds"` // 消息保留周期。取值范围60-1296000秒(1min-15天),默认值345600秒(4 天)。
|
||||
CreateTime int `json:"createTime"` // 队列的创建时间。返回 Unix 时间戳,精确到秒。
|
||||
LastModifyTime int `json:"lastModifyTime"` // 最后一次修改队列属性的时间。返回 Unix 时间戳,精确到秒。
|
||||
ActiveMsgNum int `json:"activeMsgNum"` // 在队列中处于 Active 状态(不处于被消费状态)的消息总数,为近似值。
|
||||
InactiveMsgNum int `json:"inactiveMsgNum"` // 在队列中处于 Inactive 状态(正处于被消费状态)的消息总数,为近似值。
|
||||
RewindSeconds int `json:"rewindSeconds"` // 回溯队列的消息回溯时间最大值,取值范围0 - 43200秒,0表示不开启消息回溯。
|
||||
RewindmsgNum int `json:"rewindmsgNum"` // 已调用 DelMsg 接口删除,但还在回溯保留时间内的消息数量。
|
||||
MinMsgTime int `json:"minMsgTime"` // 消息最小未消费时间,单位为秒。
|
||||
QueueName string `json:"queueName"` // 消息队列名字。
|
||||
QueueId string `json:"queueId"` // 消息队列ID。
|
||||
CreateUin int64 `json:"createUin"` // 创建者Uin。
|
||||
Bps int `json:"Bps"` // 带宽限制。
|
||||
Qps int `json:"qps"` // 每秒钟生产消息条数的限制,消费消息的大小是该值的1.1倍。
|
||||
Tags []string `json:"tags"` // 关联的标签。
|
||||
}
|
||||
|
||||
func NewGetQueueAttributesResponse() *GetQueueAttributesResponse {
|
||||
return &GetQueueAttributesResponse{}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 消费消息请求对象
|
||||
type ReceiveMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 本次请求的长轮询等待时间。取值范围0 - 30秒,如果不设置该参数,则默认使用队列属性中的 pollingWaitSeconds 值。
|
||||
pollingWaitSeconds int
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *ReceiveMessageRequest) GetActionName() string {
|
||||
return "ReceiveMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequestObject 设置公共请求对象
|
||||
func (this *ReceiveMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *ReceiveMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
paramMap["pollingWaitSeconds"] = fmt.Sprintf("%d", this.pollingWaitSeconds)
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewReceiveMessageRequest(pollingWaitSeconds int) *ReceiveMessageRequest {
|
||||
return &ReceiveMessageRequest{
|
||||
pollingWaitSeconds: pollingWaitSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
// 消费消息请求返回结果对象
|
||||
type ReceiveMessageResponse struct {
|
||||
*CommonResponse
|
||||
|
||||
// 消息对象
|
||||
*MessageInfo
|
||||
}
|
||||
|
||||
func NewReceiveMessageResponse() *ReceiveMessageResponse {
|
||||
return &ReceiveMessageResponse{}
|
||||
}
|
||||
58
trunk/framework/mqMgr/model/request_response_SendMessage.go
Normal file
58
trunk/framework/mqMgr/model/request_response_SendMessage.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 发送消息请求对象
|
||||
type SendMessageRequest struct {
|
||||
// 公共请求参数
|
||||
common *CommonRequest
|
||||
|
||||
// 消息正文
|
||||
msgBody string
|
||||
|
||||
// 单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
|
||||
delaySeconds int
|
||||
}
|
||||
|
||||
// 获取请求方法名
|
||||
func (this *SendMessageRequest) GetActionName() string {
|
||||
return "SendMessage"
|
||||
}
|
||||
|
||||
// SetCommonRequest 设置公共请求对象
|
||||
func (this *SendMessageRequest) SetCommonRequest(commonRequest *CommonRequest) {
|
||||
this.common = commonRequest
|
||||
}
|
||||
|
||||
// AssembleParamMap 组装参数字典
|
||||
// 返回值
|
||||
// map[string]string:请求参数字典
|
||||
func (this *SendMessageRequest) AssembleParamMap() map[string]string {
|
||||
paramMap := this.common.AssembleParamMap()
|
||||
paramMap["msgBody"] = this.msgBody
|
||||
paramMap["delaySeconds"] = fmt.Sprintf("%d", this.delaySeconds)
|
||||
|
||||
return paramMap
|
||||
}
|
||||
|
||||
func NewSendMessageRequest(msgBody string, delaySeconds int) *SendMessageRequest {
|
||||
return &SendMessageRequest{
|
||||
msgBody: msgBody,
|
||||
delaySeconds: delaySeconds,
|
||||
}
|
||||
}
|
||||
|
||||
// 发送消息请求返回结果对象
|
||||
type SendMessageResponse struct {
|
||||
// 公共请求结果
|
||||
*CommonResponse
|
||||
|
||||
// 服务器生成消息的唯一标识Id
|
||||
MsgId string `json:"msgId"`
|
||||
}
|
||||
|
||||
func NewSendMessageResponse() *SendMessageResponse {
|
||||
return &SendMessageResponse{}
|
||||
}
|
||||
9
trunk/framework/mqMgr/model/resultStatus.go
Normal file
9
trunk/framework/mqMgr/model/resultStatus.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package model
|
||||
|
||||
// 返回结果状态
|
||||
type ResultStatus int
|
||||
|
||||
const (
|
||||
Success = 0
|
||||
NoMessage = 7000
|
||||
)
|
||||
7
trunk/framework/mqMgr/network.go
Normal file
7
trunk/framework/mqMgr/network.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package mqMgr
|
||||
|
||||
// 网络类型:内网、外网
|
||||
const (
|
||||
MQ_NETWORK_INTERNAL = "tencentyun"
|
||||
MQ_NETWORK_PUBLIC = "tencenttdmq" //"qcloud" //todo:切换成tdmq之后,该值需要修改成:tencenttdmq
|
||||
)
|
||||
378
trunk/framework/mqMgr/queue.go
Normal file
378
trunk/framework/mqMgr/queue.go
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
我们使用腾讯云的CMQ作为公司的消息队列基础服务
|
||||
产品的说明文档:https://cloud.tencent.com/document/product/406
|
||||
*/
|
||||
package mqMgr
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
. "Framework/mqMgr/model"
|
||||
"goutil/webUtil"
|
||||
)
|
||||
|
||||
const (
|
||||
EMPTY_MESSAGE_ERROR = "消息为空"
|
||||
EMPTY_HANDLE_ERROR = "句柄为空"
|
||||
MIN_DELAY_SECONDS = 0
|
||||
MIN_POLLING_WAIT_SECONDS = 0
|
||||
MAX_POLLING_WAIT_SECONDS = 30
|
||||
MAX_BATCH_COUNT = 16
|
||||
EMPTY_BATCH_LIST_ERROR = "批量消息为空"
|
||||
EXCEED_MAX_BATCH_COUNT_ERROR = "批量消息数量超过上限,最多为16条"
|
||||
)
|
||||
|
||||
// Queue对象
|
||||
type Queue struct {
|
||||
// 地域
|
||||
region string
|
||||
|
||||
// 网络类型:内网、外网
|
||||
network string
|
||||
|
||||
// 队列名称
|
||||
queueName string
|
||||
|
||||
// API密钥Id
|
||||
secretId string
|
||||
|
||||
// API密钥key
|
||||
secretKey string
|
||||
}
|
||||
|
||||
// 执行操作
|
||||
func (this *Queue) action(requestObj IRequest, responseObj interface{}) error {
|
||||
requestObj.SetCommonRequest(NewCommonRequest(requestObj.GetActionName(), this.region, this.secretId, this.queueName))
|
||||
|
||||
// 组装请求url
|
||||
paramMap := requestObj.AssembleParamMap()
|
||||
url, signature, err := AssembleUrl(this.region, this.network, MQ_TYPE_QUEUE, this.secretKey, paramMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
paramMap["Signature"] = signature
|
||||
|
||||
//请求url,请求头
|
||||
header := webUtil.GetFormHeader()
|
||||
transport := webUtil.NewTransport()
|
||||
transport.DisableKeepAlives = true
|
||||
transport = webUtil.GetTimeoutTransport(transport, 10)
|
||||
|
||||
statusCode, result, err := webUtil.PostMapData(url, paramMap, header, transport)
|
||||
//statusCode, result, err := webUtil.PostMapData(url, paramMap, header, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if statusCode != 200 {
|
||||
return fmt.Errorf("Wrong status from server:%d", statusCode)
|
||||
}
|
||||
|
||||
// 解析请求结果
|
||||
err = json.Unmarshal(result, responseObj)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 处理发送消息延迟的时间
|
||||
func (this *Queue) handleDelaySeconds(delaySeconds int) int {
|
||||
if delaySeconds < MIN_DELAY_SECONDS {
|
||||
delaySeconds = MIN_DELAY_SECONDS
|
||||
}
|
||||
|
||||
return delaySeconds
|
||||
}
|
||||
|
||||
// 处理当没有消息是轮询等待的时间
|
||||
func (this *Queue) handlePollingWaitSeconds(pollingWaitSeconds int) int {
|
||||
if pollingWaitSeconds < MIN_POLLING_WAIT_SECONDS {
|
||||
pollingWaitSeconds = MIN_POLLING_WAIT_SECONDS
|
||||
} else if pollingWaitSeconds > MAX_POLLING_WAIT_SECONDS {
|
||||
pollingWaitSeconds = MAX_POLLING_WAIT_SECONDS
|
||||
}
|
||||
|
||||
return pollingWaitSeconds
|
||||
}
|
||||
|
||||
// 验证批量处理的列表
|
||||
func (this *Queue) validBatchList(list []string) error {
|
||||
if list == nil || len(list) == 0 {
|
||||
return errors.New(EMPTY_BATCH_LIST_ERROR)
|
||||
}
|
||||
if len(list) > MAX_BATCH_COUNT {
|
||||
return errors.New(EXCEED_MAX_BATCH_COUNT_ERROR)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// error:错误对象
|
||||
func (this *Queue) GetQueueAttributes() (err error) {
|
||||
// 逻辑处理
|
||||
requestObj := NewGetQueueAttributesRequest()
|
||||
responseObj := NewGetQueueAttributesResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SendMessage 发送单条消息
|
||||
// 参数
|
||||
// message:消息内容
|
||||
// delaySeconds:单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
|
||||
// 返回值
|
||||
// error:错误对象
|
||||
func (this *Queue) SendMessage(message string, delaySeconds int) (err error) {
|
||||
// 参数验证和处理
|
||||
if message == "" {
|
||||
err = errors.New(EMPTY_MESSAGE_ERROR)
|
||||
return
|
||||
}
|
||||
delaySeconds = this.handleDelaySeconds(delaySeconds)
|
||||
|
||||
// 逻辑处理
|
||||
requestObj := NewSendMessageRequest(message, delaySeconds)
|
||||
responseObj := NewSendMessageResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BatchSendMessage 批量发送消息
|
||||
// 参数
|
||||
// messageList:消息内容列表
|
||||
// delaySeconds:单位为秒,表示该消息发送到队列后,需要延时多久用户才可见该消息。
|
||||
// 返回值
|
||||
// error:错误对象
|
||||
func (this *Queue) BatchSendMessage(messageList []string, delaySeconds int) (err error) {
|
||||
// 参数验证和处理
|
||||
err = this.validBatchList(messageList)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
delaySeconds = this.handleDelaySeconds(delaySeconds)
|
||||
|
||||
// 逻辑处理
|
||||
requestObj := NewBatchSendMessageRequest(messageList, delaySeconds)
|
||||
responseObj := NewBatchSendMessageResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Receive 消费单条消息
|
||||
// pollingWaitSeconds:本次请求的长轮询等待时间。取值范围0 - 30秒,如果不设置该参数,则默认使用队列属性中的 pollingWaitSeconds 值。
|
||||
// 返回值
|
||||
// receiptHandle:消息句柄
|
||||
// message:消息内容
|
||||
// exist:是否存在数据
|
||||
// err:错误对象
|
||||
func (this *Queue) ReceiveMessage(pollingWaitSeconds int) (receiptHandle, message string, exist bool, err error) {
|
||||
// 参数验证和处理
|
||||
pollingWaitSeconds = this.handlePollingWaitSeconds(pollingWaitSeconds)
|
||||
|
||||
// 逻辑处理
|
||||
requestObj := NewReceiveMessageRequest(pollingWaitSeconds)
|
||||
responseObj := NewReceiveMessageResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 忽略掉没有消息的错误
|
||||
if responseObj.HaveNoMessage() {
|
||||
return
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
return
|
||||
}
|
||||
|
||||
receiptHandle = responseObj.ReceiptHandle
|
||||
message = responseObj.MsgBody
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BatchReceiveMessage 批量消费消息
|
||||
// 参数
|
||||
// numOfMsg:本次消费的消息数量
|
||||
// pollingWaitSeconds:本次请求的长轮询等待时间。取值范围0 - 30秒,如果不设置该参数,则默认使用队列属性中的 pollingWaitSeconds 值。
|
||||
// 返回值
|
||||
// receiptHandleList:消息句柄列表
|
||||
// messageList:消息内容列表
|
||||
// exist:是否存在数据
|
||||
// err:错误对象
|
||||
func (this *Queue) BatchReceiveMessage(numOfMsg, pollingWaitSeconds int) (receiptHandleList, messageList []string, exist bool, err error) {
|
||||
// 参数验证和处理
|
||||
if numOfMsg > MAX_BATCH_COUNT {
|
||||
err = errors.New(EXCEED_MAX_BATCH_COUNT_ERROR)
|
||||
return
|
||||
}
|
||||
pollingWaitSeconds = this.handlePollingWaitSeconds(pollingWaitSeconds)
|
||||
|
||||
// 逻辑处理
|
||||
requestObj := NewBatchReceiveMessageRequest(numOfMsg, pollingWaitSeconds)
|
||||
responseObj := NewBatchReceiveMessageResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 忽略掉没有消息的错误
|
||||
if responseObj.HaveNoMessage() {
|
||||
return
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
return
|
||||
}
|
||||
|
||||
// 组装返回
|
||||
receiptHandleList = make([]string, 0, numOfMsg)
|
||||
messageList = make([]string, 0, numOfMsg)
|
||||
for _, msgInfo := range responseObj.MsgInfoList {
|
||||
receiptHandleList = append(receiptHandleList, msgInfo.ReceiptHandle)
|
||||
messageList = append(messageList, msgInfo.MsgBody)
|
||||
}
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMessage 删除单条消息
|
||||
// 参数
|
||||
// receiptHandle:消息句柄
|
||||
// 返回值
|
||||
// error:错误对象
|
||||
func (this *Queue) DeleteMessage(receiptHandle string) (err error) {
|
||||
// 参数验证和处理
|
||||
if receiptHandle == "" {
|
||||
err = errors.New(EMPTY_HANDLE_ERROR)
|
||||
return
|
||||
}
|
||||
|
||||
// 逻辑处理
|
||||
requestObj := NewDeleteMessageRequest(receiptHandle)
|
||||
responseObj := NewDeleteMessageResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BatchDeleteMessage 批量删除消息
|
||||
// 参数
|
||||
// receiptHandleList:消息句柄列表
|
||||
// 返回值
|
||||
// errorMap:删除错误的字典(key:删除失败的消息句柄;value:删除失败的原因)
|
||||
// err:错误对象
|
||||
func (this *Queue) BatchDeleteMessage(receiptHandleList []string) (errorMap map[string]string, err error) {
|
||||
// 参数验证和处理
|
||||
err = this.validBatchList(receiptHandleList)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 逻辑处理
|
||||
requestObj := NewBatchDeleteMessageRequest(receiptHandleList)
|
||||
responseObj := NewBatchDeleteMessageResponse()
|
||||
|
||||
// 发送请求
|
||||
err = this.action(requestObj, &responseObj)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if responseObj.IsFailure() {
|
||||
err = errors.New(responseObj.Message)
|
||||
// 组装返回
|
||||
errorMap = make(map[string]string)
|
||||
for _, errInfo := range responseObj.ErrorList {
|
||||
errorMap[errInfo.ReceiptHandle] = errInfo.Message
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 创建新的Queue对象
|
||||
func NewQueue(region, queueName, secretId, secretKey string) *Queue {
|
||||
queueConfigObj := &QueueConfig{
|
||||
Region: region,
|
||||
QueueName: queueName,
|
||||
SecretId: secretId,
|
||||
SecretKey: secretKey,
|
||||
}
|
||||
|
||||
return NewQueueByConfig(queueConfigObj)
|
||||
}
|
||||
|
||||
// 通过队列配置对象创建新的Queue对象
|
||||
func NewQueueByConfig(queueConfigObj *QueueConfig) *Queue {
|
||||
queueObj := &Queue{
|
||||
region: queueConfigObj.Region,
|
||||
network: MQ_NETWORK_INTERNAL,
|
||||
queueName: queueConfigObj.QueueName,
|
||||
secretId: queueConfigObj.SecretId,
|
||||
secretKey: queueConfigObj.SecretKey,
|
||||
}
|
||||
|
||||
err := queueObj.GetQueueAttributes()
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), MQ_NETWORK_INTERNAL) {
|
||||
queueObj.network = MQ_NETWORK_PUBLIC
|
||||
}
|
||||
}
|
||||
|
||||
return queueObj
|
||||
}
|
||||
183
trunk/framework/mqMgr/queueHSY.go
Normal file
183
trunk/framework/mqMgr/queueHSY.go
Normal file
@@ -0,0 +1,183 @@
|
||||
package mqMgr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
)
|
||||
|
||||
// Queue对象
|
||||
type HSYQueue struct {
|
||||
conn *amqp.Connection
|
||||
channel *amqp.Channel
|
||||
// 队列名称
|
||||
queueName string
|
||||
// 交换机
|
||||
exchange string
|
||||
// routing Key
|
||||
routingKey string
|
||||
//MQ链接字符串
|
||||
mqurl string
|
||||
}
|
||||
|
||||
// 消息队列配置对象
|
||||
type HSYQueueConfig struct {
|
||||
QueueName string
|
||||
Exchange string
|
||||
RoutingKey string
|
||||
Network string
|
||||
Port int
|
||||
UserName string
|
||||
Password string
|
||||
}
|
||||
|
||||
// 创建新的Queue对象
|
||||
func NewHSYQueue(queueName, exchange, routingKey, userName, password string, network string, port int) *HSYQueue {
|
||||
queueConfigObj := &HSYQueueConfig{
|
||||
QueueName: queueName,
|
||||
Exchange: exchange,
|
||||
RoutingKey: routingKey,
|
||||
UserName: userName,
|
||||
Password: password,
|
||||
Network: network,
|
||||
Port: port,
|
||||
}
|
||||
|
||||
return NewHSYQueueByConfig(queueConfigObj)
|
||||
}
|
||||
|
||||
// 通过队列配置对象创建新的Queue对象
|
||||
func NewHSYQueueByConfig(queueConfigObj *HSYQueueConfig) *HSYQueue {
|
||||
queueObj := &HSYQueue{
|
||||
queueName: queueConfigObj.QueueName,
|
||||
exchange: queueConfigObj.Exchange,
|
||||
routingKey: queueConfigObj.RoutingKey,
|
||||
mqurl: fmt.Sprintf("amqp://%s:%s@%s:%d/", queueConfigObj.UserName, queueConfigObj.Password, queueConfigObj.Network, queueConfigObj.Port),
|
||||
}
|
||||
|
||||
if err := queueObj.GetQueueAttributes(); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return queueObj
|
||||
}
|
||||
|
||||
// 连接RabbitMQ服务器
|
||||
func (this *HSYQueue) GetQueueAttributes() (err error) {
|
||||
this.conn, err = amqp.Dial(this.mqurl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
this.channel, err = this.conn.Channel()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 释放连接
|
||||
func (this *HSYQueue) ReleaseRes() {
|
||||
this.conn.Close()
|
||||
this.channel.Close()
|
||||
}
|
||||
|
||||
// SendMessage 发送单条消息
|
||||
func (this *HSYQueue) SendMessage(message string, ex string) (err error) {
|
||||
// 声明队列
|
||||
_, err = this.channel.QueueDeclare(
|
||||
this.queueName, // 队列名
|
||||
true, // 是否持久化
|
||||
false, // 是否自动删除(前提是至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。注意:生产者客户端创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列)
|
||||
false, // 是否为排他队列(排他的队列仅对“首次”声明的conn可见[一个conn中的其他channel也能访问该队列],conn结束后队列删除)
|
||||
false, // 是否阻塞
|
||||
nil, // 额外属性
|
||||
)
|
||||
if err != nil {
|
||||
err = errors.New("声明队列失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 声明交换器
|
||||
err = this.channel.ExchangeDeclare(
|
||||
this.exchange, //交换器名
|
||||
ex, //exchange type:一般用fanout、direct、topic
|
||||
true, // 是否持久化
|
||||
false, //是否自动删除(自动删除的前提是至少有一个队列或者交换器与这和交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑)
|
||||
false, //设置是否内置的。true表示是内置的交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器这种方式
|
||||
false, // 是否阻塞
|
||||
nil, // 额外属性
|
||||
)
|
||||
if err != nil {
|
||||
err = errors.New("声明交换器失败")
|
||||
return
|
||||
}
|
||||
|
||||
// Binding
|
||||
err = this.channel.QueueBind(
|
||||
this.queueName, // 绑定的队列名称
|
||||
this.routingKey, // bindkey 用于消息路由分发的key
|
||||
this.exchange, // 绑定的exchange名
|
||||
false, // 是否阻塞
|
||||
nil, // 额外属性
|
||||
)
|
||||
if err != nil {
|
||||
err = errors.New("绑定队列和交换器失败")
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
err = this.channel.PublishWithContext(ctx,
|
||||
this.exchange,
|
||||
this.routingKey,
|
||||
false,
|
||||
false,
|
||||
amqp.Publishing{
|
||||
ContentType: "text/plain",
|
||||
Body: []byte(message),
|
||||
})
|
||||
if err != nil {
|
||||
err = errors.New("发布消息失败")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ReceiveMessage 消费单条消息
|
||||
func (this *HSYQueue) ReceiveMessage() (msgs <-chan amqp.Delivery, err error) {
|
||||
_, err = this.channel.QueueDeclare(
|
||||
this.queueName, // 队列名
|
||||
true, // 是否持久化
|
||||
false, // 是否自动删除(前提是至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。注意:生产者客户端创建这个队列,或者没有消费者客户端与这个队列连接时,都不会自动删除这个队列)
|
||||
false, // 是否为排他队列(排他的队列仅对“首次”声明的conn可见[一个conn中的其他channel也能访问该队列],conn结束后队列删除)
|
||||
false, // 是否阻塞
|
||||
nil, // 额外属性(我还不会用)
|
||||
)
|
||||
if err != nil {
|
||||
err = errors.New("声明队列失败")
|
||||
return
|
||||
}
|
||||
|
||||
msgs, err = this.channel.Consume(
|
||||
this.queueName, // 队列名
|
||||
"", // 消费者名,用来区分多个消费者,以实现公平分发或均等分发策略
|
||||
true, // 是否自动应答
|
||||
false, // 是否排他
|
||||
false, // 是否接收只同一个连接中的消息,若为true,则只能接收别的conn中发送的消息
|
||||
true, // 队列消费是否阻塞
|
||||
nil, // 额外属性
|
||||
)
|
||||
if err != nil {
|
||||
err = errors.New("获取消息失败")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
44
trunk/framework/mqMgr/queueHSY_test.go
Normal file
44
trunk/framework/mqMgr/queueHSY_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package mqMgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
queueHSYObj = NewHSYQueue("q-1", "ex-1", "rkey-1", "guest", "guest", "127.0.0.1", 5672)
|
||||
)
|
||||
|
||||
func TestHSYSendMessage(t *testing.T) {
|
||||
message := "这是测试内容. Test"
|
||||
|
||||
if queueHSYObj == nil {
|
||||
fmt.Println("初始化失败")
|
||||
return
|
||||
}
|
||||
defer queueHSYObj.ReleaseRes()
|
||||
|
||||
err := queueHSYObj.SendMessage(message, "direct")
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
go func() {
|
||||
msgs, err := queueHSYObj.ReceiveMessage()
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
for msg := range msgs {
|
||||
fmt.Println("收到消息", string(msg.Body))
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
179
trunk/framework/mqMgr/queue_test.go
Normal file
179
trunk/framework/mqMgr/queue_test.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package mqMgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
queueObj = NewQueue(MQ_REGION_GUANGZHOU, "AD-Click", "AKIDjBUWGmIkDPJHCqRb2DCQM2RbUUL1MWMx", "RcldV6PRCBwUkjGVdVjiPq0IJ2VhEZtO")
|
||||
)
|
||||
|
||||
func TestHandleDelaySeconds(t *testing.T) {
|
||||
delaySeconds := -1
|
||||
expected := 0
|
||||
delaySeconds = queueObj.handleDelaySeconds(delaySeconds)
|
||||
if delaySeconds != expected {
|
||||
t.Errorf("Expected %d, but now got %d", expected, delaySeconds)
|
||||
}
|
||||
|
||||
delaySeconds = 10
|
||||
expected = 10
|
||||
delaySeconds = queueObj.handleDelaySeconds(delaySeconds)
|
||||
if delaySeconds != expected {
|
||||
t.Errorf("Expected %d, but now got %d", expected, delaySeconds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlePollingWaitSeconds(t *testing.T) {
|
||||
pollingWaitSeconds := -1
|
||||
expected := 0
|
||||
pollingWaitSeconds = queueObj.handlePollingWaitSeconds(pollingWaitSeconds)
|
||||
if pollingWaitSeconds != expected {
|
||||
t.Errorf("Expected %d, but now got %d", expected, pollingWaitSeconds)
|
||||
}
|
||||
|
||||
pollingWaitSeconds = 100
|
||||
expected = 30
|
||||
pollingWaitSeconds = queueObj.handlePollingWaitSeconds(pollingWaitSeconds)
|
||||
if pollingWaitSeconds != expected {
|
||||
t.Errorf("Expected %d, but now got %d", expected, pollingWaitSeconds)
|
||||
}
|
||||
|
||||
pollingWaitSeconds = 15
|
||||
expected = 15
|
||||
pollingWaitSeconds = queueObj.handlePollingWaitSeconds(pollingWaitSeconds)
|
||||
if pollingWaitSeconds != expected {
|
||||
t.Errorf("Expected %d, but now got %d", expected, pollingWaitSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidBatchList(t *testing.T) {
|
||||
var list []string
|
||||
expected := EMPTY_BATCH_LIST_ERROR
|
||||
err := queueObj.validBatchList(list)
|
||||
if err == nil {
|
||||
t.Errorf("There should be an error, but now there isn't")
|
||||
}
|
||||
if err.Error() != expected {
|
||||
t.Errorf("Expected %s, but now got %s", EMPTY_BATCH_LIST_ERROR, err.Error())
|
||||
}
|
||||
|
||||
list = make([]string, 0, 16)
|
||||
expected = EMPTY_BATCH_LIST_ERROR
|
||||
err = queueObj.validBatchList(list)
|
||||
if err == nil {
|
||||
t.Errorf("There should be an error, but now there isn't")
|
||||
}
|
||||
if err.Error() != expected {
|
||||
t.Errorf("Expected %s, but now got %s", EMPTY_BATCH_LIST_ERROR, err.Error())
|
||||
}
|
||||
|
||||
for i := 0; i <= 2*MAX_BATCH_COUNT; i++ {
|
||||
list = append(list, fmt.Sprintf("Test.%d", i))
|
||||
}
|
||||
|
||||
expected = EXCEED_MAX_BATCH_COUNT_ERROR
|
||||
err = queueObj.validBatchList(list)
|
||||
if err == nil {
|
||||
t.Errorf("There should be an error, but now there isn't")
|
||||
}
|
||||
if err.Error() != expected {
|
||||
t.Errorf("Expected %s, but now got %s", EMPTY_BATCH_LIST_ERROR, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendMessage(t *testing.T) {
|
||||
message := "这是测试内容. Test"
|
||||
|
||||
// SendMessage
|
||||
err := queueObj.SendMessage(message, 0)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// ReceiveMessage
|
||||
receiptHandle, actualMessage, exist, err := queueObj.ReceiveMessage(3)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is: %s", err)
|
||||
return
|
||||
}
|
||||
if exist == false {
|
||||
t.Errorf("There should be one message, but now it's empty.")
|
||||
return
|
||||
}
|
||||
if message != actualMessage {
|
||||
t.Errorf("Expected %s, but got %s", message, actualMessage)
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteMessage
|
||||
err = queueObj.DeleteMessage(receiptHandle)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is:%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Verify
|
||||
_, _, exist, err = queueObj.ReceiveMessage(3)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is: %s", err)
|
||||
return
|
||||
}
|
||||
if exist {
|
||||
t.Errorf("There should be no message, but now there is.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestBatchSendMessage(t *testing.T) {
|
||||
count := 5
|
||||
messageList := make([]string, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
messageList = append(messageList, fmt.Sprintf("This is for test:%d", i+1))
|
||||
}
|
||||
|
||||
// BatchSendMessage
|
||||
err := queueObj.BatchSendMessage(messageList, 0)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is:%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// BatchReceiveMessage
|
||||
receiptHandleList, retMessageList, exist, err := queueObj.BatchReceiveMessage(count, 3)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is:%s", err)
|
||||
return
|
||||
}
|
||||
if !exist || messageList == nil || len(messageList) != count {
|
||||
t.Errorf("There should be %d messages, but now there isn't.", count)
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
if messageList[i] != retMessageList[i] {
|
||||
t.Errorf("Expected %s, but got %s", messageList[i], retMessageList[i])
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// BatchDeleteMessage
|
||||
_, err = queueObj.BatchDeleteMessage(receiptHandleList)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is:%s", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Verify
|
||||
_, _, exist, err = queueObj.ReceiveMessage(3)
|
||||
if err != nil {
|
||||
t.Errorf("There should be no error, but now there is: %s", err)
|
||||
return
|
||||
}
|
||||
if exist {
|
||||
t.Errorf("There should be no message, but now there is.")
|
||||
return
|
||||
}
|
||||
}
|
||||
18
trunk/framework/mqMgr/region.go
Normal file
18
trunk/framework/mqMgr/region.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package mqMgr
|
||||
|
||||
// 地域
|
||||
const (
|
||||
MQ_REGION_GUANGZHOU = "gz"
|
||||
MQ_REGION_SAHNGHAI = "sh"
|
||||
MQ_REGION_BEIJING = "bj"
|
||||
MQ_REGION_SHANGHAIJINRONG = "shjr"
|
||||
MQ_REGION_SHENZHENJINRONG = "szjr"
|
||||
MQ_REGION_HONGKONG = "hk"
|
||||
MQ_REGION_CHENGDU = "cd"
|
||||
MQ_REGION_CANADA = "ca"
|
||||
MQ_REGION_UNITED_STATES_EAST = "use"
|
||||
MQ_REGION_UNITED_STATES_WEST = "usw"
|
||||
MQ_REGION_INDIA = "in"
|
||||
MQ_REGION_THILAND = "th"
|
||||
MQ_REGION_SINGAPORE = "sg"
|
||||
)
|
||||
7
trunk/framework/mqMgr/type.go
Normal file
7
trunk/framework/mqMgr/type.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package mqMgr
|
||||
|
||||
// 消息队列类型:消息队列、消息主题
|
||||
const (
|
||||
MQ_TYPE_QUEUE = "queue"
|
||||
MQ_TYPE_TOPIC = "topic"
|
||||
)
|
||||
129
trunk/framework/mqMgr/url.go
Normal file
129
trunk/framework/mqMgr/url.go
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
url的格式如下:https://cmq-{$type}-{$region}.api.{$network}.com
|
||||
其最终内容受到以下因素的影响:地域、网络、消息队列模型
|
||||
|
||||
地域
|
||||
gz(广州)、sh(上海)、bj(北京)、shjr(上海金融)、szjr(深圳金融)、hk(中国香港)、cd(成都)、ca(北美)、usw(美西)、use(美东)、in(印度)、th(泰国)、sg(新加坡)
|
||||
|
||||
网络
|
||||
外网接口请求域名后缀:api.qcloud.com
|
||||
内网接口请求域名后缀:api.tencentyun.com
|
||||
|
||||
队列模型
|
||||
请参照下面说明将域名中的 {$region} 替换成相应地域:
|
||||
外网接口请求域名:https://cmq-queue-{$region}.api.qcloud.com
|
||||
内网接口请求域名:http://cmq-queue-{$region}.api.tencentyun.com
|
||||
|
||||
主题模型
|
||||
请参照下面说明将域名中的 {$region} 替换成相应地域:
|
||||
外网接口请求域名:https://cmq-topic-{$region}.api.qcloud.com
|
||||
内网接口请求域名:http://cmq-topic-{$region}.api.tencentyun.com
|
||||
*/
|
||||
package mqMgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"goutil/securityUtil"
|
||||
"goutil/stringUtil"
|
||||
"goutil/webUtil"
|
||||
)
|
||||
|
||||
func getPrefix(network string) string {
|
||||
if network == MQ_NETWORK_INTERNAL {
|
||||
return "http://"
|
||||
}
|
||||
|
||||
return "https://"
|
||||
}
|
||||
|
||||
// // 获取请求url
|
||||
// // region:地域
|
||||
// // network:网络类型:内网、外网
|
||||
// // _type:消息队列类型:消息队列、消息主题
|
||||
// // 返回:
|
||||
// // 请求url
|
||||
// func getHost(region, network, _type string) string {
|
||||
// url := "cmq-{$type}-{$region}.api.{$network}.com"
|
||||
// url = strings.Replace(url, "{$region}", region, 1)
|
||||
// url = strings.Replace(url, "{$network}", network, 1)
|
||||
// url = strings.Replace(url, "{$type}", _type, 1)
|
||||
|
||||
// return url
|
||||
// }
|
||||
|
||||
// 获取请求url todo:切换成tdmq之后需要用这个方法
|
||||
// region:地域
|
||||
// network:网络类型:内网、外网
|
||||
// _type:消息队列类型:消息队列、消息主题
|
||||
// 返回:
|
||||
// 请求url
|
||||
func getHost(region, network, _type string) string {
|
||||
var url string = ""
|
||||
if network == MQ_NETWORK_INTERNAL {
|
||||
url = "{$region}.mqadapter.cmq.{$network}.com"
|
||||
} else {
|
||||
url = "cmq-{$region}.public.{$network}.com"
|
||||
}
|
||||
|
||||
url = strings.Replace(url, "{$region}", region, 1)
|
||||
url = strings.Replace(url, "{$network}", network, 1)
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func getPath() string {
|
||||
return "/v2/index.php"
|
||||
}
|
||||
|
||||
func getMethod() string {
|
||||
return "POST"
|
||||
}
|
||||
|
||||
// AssembleUrl 组装请求url
|
||||
// 参数
|
||||
// region:地域
|
||||
// network:网络类型:内网、外网
|
||||
// _type:消息队列类型:消息队列、消息主题
|
||||
// secretKey:密钥的key
|
||||
// paramMap:参数字典
|
||||
// 返回值
|
||||
// string:组装好的请求url
|
||||
// string:签名
|
||||
// error:错误
|
||||
func AssembleUrl(region, network, _type, secretKey string, paramMap map[string]string) (url, signature string, err error) {
|
||||
// 1. 申请安全凭证(已经得到)
|
||||
|
||||
// 2. 生成签名串
|
||||
// 2.1、对参数排序
|
||||
// 2.2、拼接请求字符串
|
||||
// 注意:
|
||||
// “参数值”为原始值而非 url 编码后的值。
|
||||
// 若输入参数中包含下划线,则需要将其转换为“.”。(指的是参数的名称,不是参数的值)
|
||||
paramStr := webUtil.AssembleRequestParamSort(paramMap, true)
|
||||
|
||||
// 2.3、拼接签名原文字符串
|
||||
host := getHost(region, network, _type)
|
||||
path := getPath()
|
||||
signatureSource := fmt.Sprintf("%s%s%s?%s", getMethod(), host, path, paramStr)
|
||||
|
||||
// 2.4、生成签名串
|
||||
data, err := securityUtil.HmacSha256(signatureSource, secretKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
signature = string(stringUtil.Base64Encode2(data))
|
||||
|
||||
// 3. 签名串编码
|
||||
// 注意:
|
||||
// 生成的签名串并不能直接作为请求参数,需要对其进行 URL 编码。
|
||||
// 如果用户的请求方法是 GET,则对所有请求参数值均需要做 URL 编码。
|
||||
// 如果是POST,则不用进行URL编码
|
||||
// signature = url.QueryEscape(signature)
|
||||
|
||||
// 将签名添加到参数集合中
|
||||
url = fmt.Sprintf("%s%s%s", getPrefix(network), host, path)
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user