增加了队列消费端处理

This commit is contained in:
2024-07-31 15:11:52 +08:00
parent 95f283ec6b
commit 1e1ce24939
24 changed files with 738 additions and 38 deletions
+284
View File
@@ -0,0 +1,284 @@
package rabbitMq
import (
"encoding/json"
"fmt"
amqp "github.com/rabbitmq/amqp091-go"
"hepa-calc-api/config"
"hepa-calc-api/global"
"hepa-calc-api/utils"
"log"
"net/url"
"sync"
"time"
)
// Client 客户端
type Client struct {
m *sync.Mutex
queueName string
logger *log.Logger
connection *amqp.Connection
channel *amqp.Channel
done chan bool
notifyConnClose chan *amqp.Error
notifyChanClose chan *amqp.Error
notifyConfirm chan amqp.Confirmation
isReady bool
}
// ConsumeS 消费端结构体
type ConsumeS struct {
QueueName string // 队列名称
ExchangeName string // 交换机名称
RoutingKey string // 路由键
Handler func(amqp.Delivery) // 回调处理方法
}
// PublishS 生产端结构体
type PublishS struct {
QueueName string // 队列名称
ExchangeName string // 交换机名称
RoutingKey string // 路由键
Message interface{} // 消息内容
Delay time.Duration // 延迟时间
}
// NewRabbitMQClient 初始化客户端
func NewRabbitMQClient() error {
var err error
m := config.C.Amqp
user := url.QueryEscape(m.User)
password := url.QueryEscape(m.Password)
dsn := fmt.Sprintf("amqp://%s:%s@%s:%d/%s", user, password, m.Host, m.Port, m.Vhost)
// 连接到 RabbitMQ 服务器
global.RabbitConn, err = amqp.Dial(dsn)
if err != nil {
return err
}
// 创建一个通道
global.RabbitChannel, err = global.RabbitConn.Channel()
if err != nil {
return err
}
return nil
}
// Publish 生产
func Publish(queueName, exchangeName, routingKey string, message interface{}) error {
err := global.RabbitChannel.ExchangeDeclare(
exchangeName, // name
"x-delayed-message", // type
true, // durable
false, // auto-deleted
false, // internal
false, // 阻塞处理
amqp.Table{"x-delayed-type": "direct"}, // arguments
)
if err != nil {
return err
}
_, err = global.RabbitChannel.QueueDeclare(
queueName, // 队列名字
true, // 消息是否持久化
false, // 不使用的时候删除队列
false, // 是否排他
false, // 是否阻塞
nil, // arguments
)
if err != nil {
return err
}
// 将队列绑定到延迟交换器
err = global.RabbitChannel.QueueBind(
queueName, // 队列名称
routingKey, // 路由键
exchangeName, // 交换器名称
false,
nil,
)
if err != nil {
return err
}
body, err := json.Marshal(message)
if err != nil {
return err
}
err = global.RabbitChannel.Publish(
exchangeName, // exchange(交换机名字)
routingKey, //
false, // 是否为无法路由的消息进行返回处理
false, // 是否对路由到无消费者队列的消息进行返回处理 RabbitMQ 3.0 废弃
amqp.Publishing{
ContentType: "text/plain",
Body: body, // 消息内容
})
if err != nil {
return err
}
return nil
}
// PublishWithDelay 生产延迟消息
func (p PublishS) PublishWithDelay() error {
err := global.RabbitChannel.ExchangeDeclare(
p.ExchangeName, // name
"x-delayed-message", // type
true, // durable
false, // auto-deleted
false, // internal
false, // 阻塞处理
amqp.Table{"x-delayed-type": "direct"}, // arguments
)
if err != nil {
return err
}
_, err = global.RabbitChannel.QueueDeclare(
p.QueueName, // 队列名字
true, // 消息是否持久化
false, // 不使用的时候删除队列
false, // 是否排他
false, // 是否阻塞
nil, // arguments
)
if err != nil {
return err
}
// 将队列绑定到延迟交换器
err = global.RabbitChannel.QueueBind(
p.QueueName, // 队列名称
p.RoutingKey, // 路由键
p.ExchangeName, // 交换器名称
false,
nil,
)
if err != nil {
return err
}
body, err := json.Marshal(p.Message)
if err != nil {
return err
}
err = global.RabbitChannel.Publish(
p.ExchangeName, // exchange
p.RoutingKey, // routing key
false, // 是否为无法路由的消息进行返回处理
false, // 是否对路由到无消费者队列的消息进行返回处理 RabbitMQ 3.0 废弃
amqp.Publishing{
ContentType: "text/plain",
Body: body,
Headers: amqp.Table{"x-delay": int32(p.Delay / time.Millisecond)},
})
if err != nil {
return err
}
return nil
}
// Consume 消费
func (s ConsumeS) Consume() error {
err := global.RabbitChannel.ExchangeDeclare(
s.ExchangeName, // name
"x-delayed-message", // type
true, // durable
false, // auto-deleted
false, // internal
false, // 阻塞处理
amqp.Table{"x-delayed-type": "direct"}, // arguments
)
if err != nil {
return err
}
queue, err := global.RabbitChannel.QueueDeclare(
s.QueueName, // 队列名称
true, // 是否持久化
false, // 是否自动删除队列
false, // 排他
false, // 阻塞处理
nil, // arguments
)
if err != nil {
return err
}
// 将队列绑定到延迟交换器
err = global.RabbitChannel.QueueBind(
s.QueueName, // 队列名称
s.RoutingKey, // 路由键
s.ExchangeName, // 交换器名称
false,
nil,
)
if err != nil {
return err
}
msgs, err := global.RabbitChannel.Consume(
queue.Name, // queue
"", // 消费者标签
false, // 是否自动确认
false, // 是否独占
false, // 是否无等待
false, //其他参数
nil, // 其他参数
)
if err != nil {
return err
}
// 消费消息
go func() {
for msg := range msgs {
s.Handler(msg)
}
}()
return nil
}
// Close 关闭rabbitMq
func Close() {
if global.RabbitChannel != nil {
err := global.RabbitChannel.Close()
if err != nil {
utils.LogJsonErr("关闭rabbitMq:", err.Error())
return
}
}
if global.RabbitConn != nil {
err := global.RabbitConn.Close()
if err != nil {
utils.LogJsonErr("关闭rabbitMq:", err.Error())
return
}
}
}
// HandleReconnect 处理重新连接
func HandleReconnect() {
for {
notifyClose := make(chan *amqp.Error)
global.RabbitConn.NotifyClose(notifyClose)
err := <-notifyClose
if err != nil {
time.Sleep(30 * time.Second)
_ = NewRabbitMQClient()
}
}
}
+4 -4
View File
@@ -13,10 +13,10 @@ import (
// 创建客户端
func createClient() (*core.Client, error) {
mchId := config.C.Wechat.Pay1659662936.MchId // 商户号
mchCertificateSerialNumber := config.C.Wechat.Pay1659662936.MchCertificateSerialNumber // 商户证书序列号
v3ApiSecret := config.C.Wechat.Pay1659662936.V3ApiSecret // 商户APIv3密钥
privateKeyPath := "extend/weChat/certs/" + config.C.Wechat.Pay1659662936.MchId + "/apiclient_key.pem" // 商户私钥文件地址
mchId := config.C.Wechat.Pay1281030301.MchId // 商户号
mchCertificateSerialNumber := config.C.Wechat.Pay1281030301.MchCertificateSerialNumber // 商户证书序列号
v3ApiSecret := config.C.Wechat.Pay1281030301.V3ApiSecret // 商户APIv3密钥
privateKeyPath := config.C.Wechat.Pay1281030301.PrivateKey // 商户私钥文件地址
if mchId == "" {
return nil, errors.New("商户号错误")
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDR4fiYRUjnLQA+
TPMslDvQIIyZm4ajWFcSXg6yozhdi/O+vuRhwgyeGXsE4SpvuxkK4HPZaocrsjqe
68Y46DyhudzXIBy50IF2UeN5ilj7ydq5TJbBOi1iOF1lgOUNK6DGiOQ+folVNKyN
sjrsA3RHUKHF/JdOfcpSGzvV79FnmjSll/KsdxEc9LCiAa5t7GYA9Hx7AIDG4i8b
03d5EJXvE8BGUZQItE6VIpHwyySTHtGQkPyI6lqMKt2Jlx0TFHu0GkTEmhuA2Z5C
5gOqYWclQO+X2ORgulL9Q3mNcpfy9uBynI/CJDbSvVTkNfwYB0Ny1knu/+in7C6p
IPJYfZpPAgMBAAECggEAWb5tJPcjSC5W10ziAiLUPJdeZ2Q4OupQOPtc/4eJV367
V8maMC7gZE3y61A4bBQtjhgRkVrat5V7OW8JkFXFb0XhJ1+EyPNeGDDFureseuWC
EA+uuqrcsw306a0mw+3uzlXEevByWquuSNx4E2katE/HDLiIHjjtZRReDomAGfLw
vLNZ40RgdNSXmwpVRoHOZnvX+C2Hxh4fKsrxs1HRCjFsSpTxKwsK6/Kdudj4hsaO
Z5glqf4qopPlQIIkToxOe5p7ukwo7vqaqogixx3jOjruOMpzxZ24wU5AxneLcOYr
ZC1659Uwv96TsKpueakWw0lq3TXkv9Qs+wDNI+NC6QKBgQDx4hWXplLYPYwgGgxG
L9Pk+If9aDS9wj78JUaYBXKR5atXmf/62ufahW4IEDfmMugC1bm9MoYC7CmHv1nk
nxckB84B20NOSiaxbkOaJuMHDtnNeXCmL8Gvtb8fTni1AM/g6XEleEw1r40LNZAq
kdyQ1+OUFhRQGOvAe1SRr1rdGwKBgQDeIcauwMPkc3Seh6Fb66FQ4Lgmt1GvvuiG
UJiwgwPFbEaKKczBHBL6hlKoAFweFa2Qw2xJ0H8jwb8RnkkNcAKYUyMc2wi85+Ih
d568pvXMdYl4DGeGdd/sXKf4dGDjcb2AHzNfDuklbCsAojtO3pLWOs5U/RSKe8ps
hhWa8nPO3QKBgQCIxuKU3X1tP+hz4qbcLYFxscQcXIeuYiABrwZrQnFV5Pxtzex9
Krn+zIK61oj1iAXATKD6Ro6XKnoVg/POHtQUEMHCNP2rUKzumj5p9eFdBV3OHgTA
RLMOrARGLLZ/C9WBBiBwIsVdekaUdxZtrAuAcEQFYjLcVCtDrbnVo8YKzwKBgEsg
V0cBMP+RwM5hBsTE45Er/3wwofLzeUb7+Tgxh1P887qEuphRO2X5ifkB7iXKpSIB
xh0M5AMe4tU9mG1wBaCo9YYr2j+xmTxCbbBWM2mMEwtD/rtuIGabS7/u9FnYPQQZ
CVHMBDRA6iZTuAVLp5PG3cPGuGzBw0uC6cm22E4NAoGAKrbg3nFPKtzBJZ8Z0iNH
G2gNotmHXbd4+gs4e3Iz9xsEabm4wCoEibNojNdMkX8zX267ebgfvesGEobROjW9
Intvh39xi3aQ2Q5gvXzKdY0lDzgVvQ7udmLQ4dCUyYnpLr7Yac0asRxLge2esCWV
x2uW2YTiUW3zsbHN/N/vJ5I=
-----END PRIVATE KEY-----
+4 -4
View File
@@ -14,10 +14,10 @@ import (
// ParseNotify 回调通知的验签与解密
func ParseNotify(c *gin.Context) (notifyReq *notify.Request, t *payments.Transaction, err error) {
mchId := config.C.Wechat.Pay1659662936.MchId // 商户号
mchCertificateSerialNumber := config.C.Wechat.Pay1659662936.MchCertificateSerialNumber // 商户证书序列号
v3ApiSecret := config.C.Wechat.Pay1659662936.V3ApiSecret // 商户APIv3密钥
privateKeyPath := "extend/weChat/certs/" + config.C.Wechat.Pay1659662936.MchId + "/apiclient_key.pem" // 商户私钥文件地址
mchId := config.C.Wechat.Pay1281030301.MchId // 商户号
mchCertificateSerialNumber := config.C.Wechat.Pay1281030301.MchCertificateSerialNumber // 商户证书序列号
v3ApiSecret := config.C.Wechat.Pay1281030301.V3ApiSecret // 商户APIv3密钥
privateKeyPath := "extend/weChat/certs/" + config.C.Wechat.Pay1281030301.MchId + "/apiclient_key.pem" // 商户私钥文件地址
// 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
mchPrivateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath)