364 lines
8.9 KiB
Markdown
364 lines
8.9 KiB
Markdown
|
|
# RabbitMQ 服务使用说明
|
|||
|
|
|
|||
|
|
## 功能概述
|
|||
|
|
|
|||
|
|
这个 RabbitMQ 服务实现了区块链支付系统的消息队列功能,包括:
|
|||
|
|
|
|||
|
|
### 消费队列(监听)
|
|||
|
|
1. **充值队列 (topup)** - 监听用户充值请求
|
|||
|
|
2. **提现队列 (withdraw)** - 监听用户提现请求
|
|||
|
|
3. **支付队列 (pay)** - 监听用户支付请求
|
|||
|
|
|
|||
|
|
### 发布队列(响应)
|
|||
|
|
1. **充值响应队列 (topup_resp)** - 发送充值确认结果
|
|||
|
|
2. **提现响应队列 (withdraw_resp)** - 发送提现确认结果
|
|||
|
|
3. **支付响应队列 (pay_resp)** - 发送支付确认结果
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 快速开始
|
|||
|
|
|
|||
|
|
### 1. 安装依赖
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
go get github.com/rabbitmq/amqp091-go
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 配置文件示例 (config.json)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"rmq_config": {
|
|||
|
|
"sub_addr": "amqp://username:password@localhost:5672",
|
|||
|
|
"pay": {
|
|||
|
|
"queue": "pay.auto.queue",
|
|||
|
|
"exchange": "pay.exchange",
|
|||
|
|
"routing": ["pay.auto.routing.key"]
|
|||
|
|
},
|
|||
|
|
"topup": {
|
|||
|
|
"queue": "pay.recharge.queue",
|
|||
|
|
"exchange": "pay.exchange",
|
|||
|
|
"routing": ["pay.recharge.routing.key"]
|
|||
|
|
},
|
|||
|
|
"withdraw": {
|
|||
|
|
"queue": "pay.withdraw.queue",
|
|||
|
|
"exchange": "pay.exchange",
|
|||
|
|
"routing": ["pay.withdraw.routing.key"]
|
|||
|
|
},
|
|||
|
|
"pay_resp": {
|
|||
|
|
"queue": "pay.auto.return.queue",
|
|||
|
|
"exchange": "pay.exchange",
|
|||
|
|
"routing": ["pay.auto.return.routing.key"]
|
|||
|
|
},
|
|||
|
|
"topup_resp": {
|
|||
|
|
"queue": "pay.recharge.return.queue",
|
|||
|
|
"exchange": "pay.exchange",
|
|||
|
|
"routing": ["pay.recharge.return.routing.key"]
|
|||
|
|
},
|
|||
|
|
"withdraw_resp": {
|
|||
|
|
"queue": "pay.withdraw.return.queue",
|
|||
|
|
"exchange": "pay.exchange",
|
|||
|
|
"routing": ["pay.withdraw.return.routing.key"]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 使用示例
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
package main
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"log"
|
|||
|
|
message "m2pool-payment/internal/msg"
|
|||
|
|
rmq "m2pool-payment/internal/queue"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
func main() {
|
|||
|
|
// 加载配置
|
|||
|
|
config := loadConfig() // 你的配置加载逻辑
|
|||
|
|
|
|||
|
|
// 创建 RabbitMQ 服务
|
|||
|
|
rmqServer, err := rmq.NewRabbitMQServer(config.RMQConfig)
|
|||
|
|
if err != nil {
|
|||
|
|
log.Fatalf("创建 RabbitMQ 服务失败: %v", err)
|
|||
|
|
}
|
|||
|
|
defer rmqServer.Close()
|
|||
|
|
|
|||
|
|
// 设置消息处理回调
|
|||
|
|
rmqServer.OnTopupMsg = func(msg message.TopupMsg_req) {
|
|||
|
|
log.Printf("收到充值请求: %+v", msg)
|
|||
|
|
// 处理充值逻辑...
|
|||
|
|
// 添加地址监听等
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rmqServer.OnWithdrawMsg = func(msg message.WithdrawMsg_req) {
|
|||
|
|
log.Printf("收到提现请求: %+v", msg)
|
|||
|
|
// 处理提现逻辑...
|
|||
|
|
// 调用区块链转账
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rmqServer.OnPayMsg = func(msg message.PayMsg_req) {
|
|||
|
|
log.Printf("收到支付请求: %+v", msg)
|
|||
|
|
// 处理支付逻辑...
|
|||
|
|
// 调用区块链转账
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 启动监听
|
|||
|
|
if err := rmqServer.Start(); err != nil {
|
|||
|
|
log.Fatalf("启动监听失败: %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 发送响应消息示例
|
|||
|
|
rmqServer.PublishTopupResp(message.TopupMsg_resp{
|
|||
|
|
Address: "0x123...",
|
|||
|
|
Status: 1,
|
|||
|
|
Chain: "ETH",
|
|||
|
|
Symbol: "USDT",
|
|||
|
|
Amount: 100.0,
|
|||
|
|
TxHash: "0xabc...",
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 保持运行
|
|||
|
|
select {}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## API 说明
|
|||
|
|
|
|||
|
|
### 创建服务
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func NewRabbitMQServer(config message.RMQConfig) (*RabbitMQServer, error)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
创建一个新的 RabbitMQ 服务实例。
|
|||
|
|
|
|||
|
|
**参数:**
|
|||
|
|
- `config`: RabbitMQ 配置
|
|||
|
|
|
|||
|
|
**返回:**
|
|||
|
|
- `*RabbitMQServer`: 服务实例
|
|||
|
|
- `error`: 错误信息
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 启动监听
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func (r *RabbitMQServer) Start() error
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
启动所有队列的监听(topup, withdraw, pay)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 消息回调设置
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 充值请求回调
|
|||
|
|
rmqServer.OnTopupMsg = func(msg message.TopupMsg_req) {
|
|||
|
|
// 处理逻辑
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 提现请求回调
|
|||
|
|
rmqServer.OnWithdrawMsg = func(msg message.WithdrawMsg_req) {
|
|||
|
|
// 处理逻辑
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 支付请求回调
|
|||
|
|
rmqServer.OnPayMsg = func(msg message.PayMsg_req) {
|
|||
|
|
// 处理逻辑
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 发布响应消息
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 发布充值响应
|
|||
|
|
func (r *RabbitMQServer) PublishTopupResp(resp message.TopupMsg_resp) error
|
|||
|
|
|
|||
|
|
// 发布提现响应
|
|||
|
|
func (r *RabbitMQServer) PublishWithdrawResp(resp message.WithdrawMsg_resp) error
|
|||
|
|
|
|||
|
|
// 发布支付响应
|
|||
|
|
func (r *RabbitMQServer) PublishPayResp(resp message.PayMsg_resp) error
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 关闭服务
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func (r *RabbitMQServer) Close() error
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
优雅关闭 RabbitMQ 连接和所有监听。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 消息格式
|
|||
|
|
|
|||
|
|
### 充值请求 (TopupMsg_req)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"chain": "ETH",
|
|||
|
|
"symbol": "USDT",
|
|||
|
|
"address": "0x123...",
|
|||
|
|
"timestamp": 1234567890,
|
|||
|
|
"sign": "signature_string"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 充值响应 (TopupMsg_resp)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"address": "0x123...",
|
|||
|
|
"status": 1,
|
|||
|
|
"chain": "ETH",
|
|||
|
|
"symbol": "USDT",
|
|||
|
|
"amount": 100.5,
|
|||
|
|
"tx_hash": "0xabc..."
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 提现请求 (WithdrawMsg_req)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"queue_id": "queue_123",
|
|||
|
|
"from_address": "0x123...",
|
|||
|
|
"to_address": "0x456...",
|
|||
|
|
"amount": 50.0,
|
|||
|
|
"chain": "ETH",
|
|||
|
|
"symbol": "USDT",
|
|||
|
|
"timestamp": 1234567890,
|
|||
|
|
"sign": "signature_string"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 提现响应 (WithdrawMsg_resp)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"queue_id": "queue_123",
|
|||
|
|
"status": 1,
|
|||
|
|
"amount": 50.0,
|
|||
|
|
"chain": "ETH",
|
|||
|
|
"symbol": "USDT",
|
|||
|
|
"tx_hash": "0xdef..."
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 支付请求 (PayMsg_req)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"queue_id": "queue_456",
|
|||
|
|
"from_address": "0x123...",
|
|||
|
|
"to_address": "0x789...",
|
|||
|
|
"amount": 200.0,
|
|||
|
|
"chain": "ETH",
|
|||
|
|
"symbol": "USDT",
|
|||
|
|
"order_id": "order_789",
|
|||
|
|
"timestamp": 1234567890,
|
|||
|
|
"sign": "signature_string"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 支付响应 (PayMsg_resp)
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"queue_id": "queue_456",
|
|||
|
|
"status": 1,
|
|||
|
|
"amount": 200.0,
|
|||
|
|
"chain": "ETH",
|
|||
|
|
"symbol": "USDT",
|
|||
|
|
"order_id": "order_789",
|
|||
|
|
"tx_hash": "0xghi..."
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 状态码说明
|
|||
|
|
|
|||
|
|
- `status = 0` - 失败
|
|||
|
|
- `status = 1` - 成功
|
|||
|
|
- `status = 2` - 待确认(仅用于链上交易)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 特性
|
|||
|
|
|
|||
|
|
✅ **自动重连** - 连接断开时自动重连
|
|||
|
|
✅ **消息持久化** - 消息不会丢失
|
|||
|
|
✅ **手动确认** - 处理成功后才确认消息
|
|||
|
|
✅ **并发安全** - 支持多 goroutine 并发发布
|
|||
|
|
✅ **优雅关闭** - 支持优雅关闭所有连接
|
|||
|
|
✅ **错误处理** - 完善的错误日志和重试机制
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
1. **连接地址格式**: `amqp://username:password@host:port/`
|
|||
|
|
2. **消息确认**: 只有处理成功的消息才会被确认,失败的消息会重新入队
|
|||
|
|
3. **并发安全**: 发布消息时使用了互斥锁,可以安全地从多个 goroutine 调用
|
|||
|
|
4. **重连机制**: 连接断开时会自动重连,间隔 3 秒
|
|||
|
|
5. **消息持久化**: 消息和队列都是持久化的,重启后不会丢失
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 工作流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
|||
|
|
│ 业务系统 │ ------> │ RabbitMQ │ ------> │ 支付系统 │
|
|||
|
|
│ │ 充值/ │ (消息队列) │ 消费 │ (本系统) │
|
|||
|
|
│ │ 提现/ │ │ │ │
|
|||
|
|
│ │ 支付 │ │ │ │
|
|||
|
|
└─────────────┘ └──────────────┘ └─────────────┘
|
|||
|
|
|
|
|||
|
|
| 监听链上
|
|||
|
|
v
|
|||
|
|
┌─────────────┐
|
|||
|
|
│ 区块链节点 │
|
|||
|
|
│ (ETH) │
|
|||
|
|
└─────────────┘
|
|||
|
|
|
|
|||
|
|
| 交易确认
|
|||
|
|
v
|
|||
|
|
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
|||
|
|
│ 业务系统 │ <------ │ RabbitMQ │ <------ │ 支付系统 │
|
|||
|
|
│ │ 响应 │ (响应队列) │ 发布 │ (本系统) │
|
|||
|
|
└─────────────┘ └──────────────┘ └─────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 故障排查
|
|||
|
|
|
|||
|
|
### 连接失败
|
|||
|
|
- 检查 RabbitMQ 服务是否运行
|
|||
|
|
- 检查用户名密码是否正确
|
|||
|
|
- 检查网络连接和端口(默认 5672)
|
|||
|
|
|
|||
|
|
### 消息未被消费
|
|||
|
|
- 检查队列绑定是否正确
|
|||
|
|
- 检查 routing key 是否匹配
|
|||
|
|
- 查看 RabbitMQ 管理界面的队列状态
|
|||
|
|
|
|||
|
|
### 消息重复消费
|
|||
|
|
- 确保消息处理成功后调用了 Ack
|
|||
|
|
- 检查是否有多个消费者实例
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 许可证
|
|||
|
|
|
|||
|
|
MIT License
|
|||
|
|
|