Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
  • 责任链模式消息校验
  • 参数拼装
  • Kafka异步下发
  • 消息隔离
  • 消息延时推送
  • 持久层
  • 渠道消息下发
  • 应用优雅关闭
  • 消息去重
  • 链路追踪
    • 埋点
    • 全链路请求参数
    • 全链路返回信息
    • 链路查询
    • 获取发送消息的全链路数据
  • 实时流处理
  • 消息推送平台
Nreal
2024-04-06
目录

链路追踪

# 埋点

埋点状态

@Getter
@ToString
@AllArgsConstructor
public enum AnchorState implements PowerfulEnum {
    /**
     * 消息接收成功(获取到请求)
     */
    RECEIVE(10, "消息接收成功"),
    /**
     * 消息被丢弃(从Kafka消费后,被丢弃)
     */
    DISCARD(20, "消费被丢弃"),
    /**
     * 消息被夜间屏蔽(模板设置了夜间屏蔽)
     */
    NIGHT_SHIELD(22, "夜间屏蔽"),
    /**
     * 消息被夜间屏蔽(模板设置了夜间屏蔽,次日9点再发送)
     */
    NIGHT_SHIELD_NEXT_SEND(24, "夜间屏蔽(次日早上9点发送)"),

    /**
     * 消息被内容去重(重复内容5min内多次发送)
     */
    CONTENT_DEDUPLICATION(30, "消息被内容去重"),
    /**
     * 消息被频次去重(同一个渠道短时间内发送多次消息给用户)
     */
    RULE_DEDUPLICATION(40, "消息被频次去重"),
    /**
     * 白名单过滤(非正式环境,不在白名单内)
     */
    WHITE_LIST(50, "白名单过滤"),
    /**
     * 下发成功(调用渠道接口成功)
     */
    SEND_SUCCESS(60, "消息下发成功"),
    /**
     * 下发失败(调用渠道接口失败)
     */
    SEND_FAIL(70, "消息下发失败"),

    /**
     * 点击(下发的消息被点击)
     */
    CLICK(64, "消息被点击");


    private final Integer code;
    private final String description;
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

埋点信息

public class SimpleAnchorInfo {

    /**
     * 具体点位
     */
    private int state;

    /**
     * 业务Id(数据追踪使用)
     * 生成逻辑参考 TaskInfoUtils
     */
    private Long businessId;

    /**
     * 生成时间
     */
    private long timestamp;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 全链路请求参数

public class DataParam {
    /**
     * 查看消息Id的链路信息
     */
    private String messageId;

    /**
     * 查看用户的链路信息
     */
    private String receiver;

    /**
     * 业务Id(数据追踪使用)
     * 如果传入的是模板ID,则生成当天的业务ID
     */
    private String businessId;

    /**
     * 日期时间(检索短信的条件使用)
     */
    private Long dateTime;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 全链路返回信息

public class TraceResponse {
    /**
     * 响应状态
     */
    private String code;
    /**
     * 响应编码
     */
    private String msg;

    /**
     * 埋点信息
     */
    private List<SimpleAnchorInfo> data;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 链路查询

基于MessageID查询链路结果;

@Service
@Primary
public class TraceServiceImpl implements TraceService {

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public TraceResponse traceByMessageId(String messageId) {
        if (CharSequenceUtil.isBlank(messageId)) {
            return new TraceResponse(RespStatusEnum.CLIENT_BAD_PARAMETERS.getCode(), RespStatusEnum.CLIENT_BAD_PARAMETERS.getMsg(), null);
        }
        String redisMessageKey = CharSequenceUtil.join(StrUtil.COLON, AustinConstant.CACHE_KEY_PREFIX, AustinConstant.MESSAGE_ID, messageId);
        List<String> messageList = redisUtils.lRange(redisMessageKey, 0, -1);
        if (CollUtil.isEmpty(messageList)) {
            return new TraceResponse(RespStatusEnum.FAIL.getCode(), RespStatusEnum.FAIL.getMsg(), null);
        }

        // 按时间排序
        List<SimpleAnchorInfo> sortAnchorList = messageList.stream().map(s -> JSON.parseObject(s, SimpleAnchorInfo.class)).sorted((o1, o2) -> Math.toIntExact(o1.getTimestamp() - o2.getTimestamp())).collect(Collectors.toList());

        return new TraceResponse(RespStatusEnum.SUCCESS.getCode(), RespStatusEnum.SUCCESS.getMsg(), sortAnchorList);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 获取发送消息的全链路数据

接口:DataController#getMessageData()

@PostMapping("/message")
@ApiOperation("/获取【72小时】发送消息的全链路数据")
public UserTimeLineVo getMessageData(@RequestBody DataParam dataParam) {
    if (Objects.isNull(dataParam) || CharSequenceUtil.isBlank(dataParam.getMessageId())) {
        return UserTimeLineVo.builder().items(new ArrayList<>()).build();
    }
    return dataService.getTraceMessageInfo(dataParam.getMessageId());
}
1
2
3
4
5
6
7
8
@Override
public UserTimeLineVo getTraceMessageInfo(String messageId) {
    TraceResponse traceResponse = traceService.traceByMessageId(messageId);
    if (CollUtil.isEmpty(traceResponse.getData())) {
        return UserTimeLineVo.builder().items(new ArrayList<>()).build();
    }
    return buildUserTimeLineVo(traceResponse.getData());
}
1
2
3
4
5
6
7
8
消息去重
实时流处理

← 消息去重 实时流处理→

Theme by Vdoing | Copyright © 2021-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式