
# 发送定时消息
分布式消息服务RocketMQ版支持**任意时间**的定时消息。
定时消息即生产者生产消息到分布式消息服务RocketMQ版后，消息不会立即被消费，而是延迟到设定的时间点后才会发送给消费者进行消费。
发送定时消息前，请参考[收集连接信息](https://support.huaweicloud.com/devg-hrm/hrm-devg-008.html)收集RocketMQ所需的连接信息。
#### 约束与限制
2022年3月30日及以后购买的实例支持定时消息功能，在此之前购买的实例不支持此功能。
#### 适用场景
定时消息适用于以下场景：
- 消息对应的业务逻辑有时间窗口要求，如电商交易中超时未支付关闭订单的场景。在订单创建时发送一条定时消息，5分钟以后投递给消费者，消费者收到此消息后需要判断对应订单是否完成支付，如果未完成支付，则关闭订单。如果已完成，则忽略。
- 通过消息触发定时任务的场景，如在某些固定时间点向用户发送提醒消息。
 
#### 注意事项
- 4.8.0版本定时消息的最大延迟时间为1年，5.x版本为7天，若延迟时间超过对应版本的最大限制（1年或7天），消息将发送失败。
- 定时消息的定时时间如果被设置成当前时间戳之前的某个时刻，消息将立刻投递给消费者。
- 无法确保定时消息仅投递一次，定时消息可能会重复投递。
- 定时消息的定时时间是服务端开始向消费端投递的时间。如果消费者当前有消息堆积，那么定时消息会排在堆积消息后面，将不能严格按照配置的时间进行投递。
- 由于客户端和服务端可能存在时间差，消息的实际投递时间与客户端设置的投递时间之间可能存在偏差，以服务端时间为准。
- 设置定时消息的投递时间后，依然受消息老化时间限制，默认消息老化时间为2天。例如，设置定时消息5天后才能被消费，如果第5天后一直没被消费，那么这条消息将在第7天被删除。
- 定时消息将占用普通消息约3倍的存储空间，大量使用定时消息时需要注意存储空间占用。
 
#### 准备环境
1. 执行以下命令，检查是否已安装Go。
   ```
   go version
   ```
   返回如下回显时，说明Go已经安装。
   ```
   go version go1.16.5 linux/amd64
   ```
   如果未安装Go，请[下载并安装](https://go.dev/dl/go1.16.5.linux-amd64.tar.gz)。
   
2. 进入Go脚本所在的bin目录下。
3. 执行"touch go.mod"命令新建一个"go.mod"，并增加以下代码，添加依赖。
   ```
   module rocketmq-example-go
   go 1.13
   require (
   github.com/apache/rocketmq-client-go/v2 v2.1.2
   )
   ```
   
4. 执行如下命令增加代理。
   ```
   export GOPROXY=https://goproxy.cn,direct
   ```
   
5. 执行如下命令下载依赖。
   ```
   go mod tidy
   ```
   
 
#### 发送定时消息
发送定时消息的示例代码如下（以下加粗内容需要替换为实例自有信息，请根据实际情况替换）。
```
package main
import (
"context"
"fmt"
"github.com/apache/rocketmq-client-go/v2"
"github.com/apache/rocketmq-client-go/v2/primitive"
"github.com/apache/rocketmq-client-go/v2/producer"
"os"
)
func main() {
p, _ := rocketmq.NewProducer(
producer.WithNsResolver(primitive.NewPassthroughResolver([]string{"192.168.0.1:8100"})),
producer.WithRetry(2),
//producer.WithTls(true), //创建实例时，如果开启了SSL，请添加此行代码。
)
err := p.Start()
if err != nil {
fmt.Printf("start producer error: %s", err.Error())
os.Exit(1)
}
msg := primitive.NewMessage("test", []byte("Hello RocketMQ Go Client!"))
msg.WithProperty("__STARTDELIVERTIME", strconv.FormatInt(time.Now().UnixMilli()+3000, 10))
res, err := p.SendSync(context.Background(), msg)
if err != nil {
fmt.Printf("send message error: %s\n", err)
} else {
fmt.Printf("send message success: result=%s\n", res.String())
}
err = p.Shutdown()
if err != nil {
fmt.Printf("shutdown producer error: %s", err.Error())
}
}
```
示例代码中的参数说明如下，请参考[收集连接信息](https://support.huaweicloud.com/devg-hrm/hrm-devg-008.html)获取参数值。
- 192.168.0.1:8100：表示实例连接地址和端口。
- test：表示Topic名称。
 
