Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,13 @@
### ✅ **已发布功能版本**
#### v1.0.0 核心能力:**生产级网络通信架构** | **企业级 VIPER 架构**
#### v1.1.0 核心能力:**多维度指标监控、全链路追踪**

#### v1.2.0 核心能力:TLV协议扩展性增强
#### v1.2.0 核心能力:根据当前App状态+网络状态,动态调整心跳频率


---

#### 网络框架
#### 网络框架(核心点)
##### ConcurrentNetworkManager
**高性能单 TCP 通信模块**(生产环境验证)
- **核心特性**
Expand Down Expand Up @@ -140,24 +141,28 @@ client.send(message: imageMessage) { error in
- **v1.1.0**:新增全链路追踪、关键指标采集(网络质量/成功率/延迟)并添加演示Demo,引入序列号分区机制,整体逻辑优化
- **v1.2.0**:协议改造为TLV结构,支持协议无缝升级,整体逻辑重构,消息构造和解析逻辑发生本质变化,详见Doc
- **v1.2.1**:完善了消息错误机制,遵循单一职责拆分了数据包解析、组装,抽象了连接管理类,优化了握手交换协议版本信息逻辑
- **v1.3.0**:升级动态心跳机制,结合App状态+网络状态,使用更成熟稳定的方案动态调整心跳频率;埋点功能优化,提供更全面的埋点维度


### 版本规划

#### 🔜v1.3.0(开发中) - 长连接优化
#### 🔜v1.4.0(规划中) - 运营商心跳优化
- **心跳保活增强**:运营商NAT超时适配
- **防拦截策略**:运营商级心跳包伪装
- **连接保持**:智能心跳间隔动态调整

#### v1.4.0(规划中) - 性能升级
#### v1.5.0(规划中) - 性能升级
- **连接池优化**:智能资源分配
- **分包策略升级**:大文件分片传输
- **QoS保障**:流量优先级控制、流量熔断

#### v1.5.0(规划中) - 极端场景优化
#### v1.6.0(规划中) - 极端场景优化
- **弱网高性能对抗**:智能降级策略
- **错误恢复**:多级故障回滚
- **协议演进**:可靠UDP传输

#### v1.7.0(规划中) - 单聊界面整理
- **IM防腐层设计**:无论当前使用自研还是第三方SDK,防腐层都有很大的必要性
- **聊天界面实战**:VIPER+当前TCP通信框架,构建实战级单聊界面

**✨ 持续迭代中,期待您的 Star 关注! ✨**

Expand All @@ -175,7 +180,7 @@ Socket通信模块架构
```
+---------------------------------------------------+
| 应用层 |
| 使用统一API管理网络通信 |
| 使用统一API管理网络通信 |
+---------------------------------------------------+
|
v
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// TJPMetricsCollector.h
// iOS-Network-Stack-Dive
//
// Created by 唐佳鹏 on 2025/4/9.
// 指标收集器

#import <Foundation/Foundation.h>
#import "TJPCoreTypes.h"

NS_ASSUME_NONNULL_BEGIN
// 以下定义渐进式迁移至 TJPMetricsKeys中统一管理

// 连接相关指标
//extern NSString * const TJPMetricsKeyConnectionAttempts;
//extern NSString * const TJPMetricsKeyConnectionSuccess;

// 心跳相关指标
//extern NSString * const TJPMetricsKeyHeartbeatSend;
//extern NSString * const TJPMetricsKeyHeartbeatLoss;
//extern NSString * const TJPMetricsKeyHeartbeatRTT;
//extern NSString * const TJPMetricsKeyHeartbeatInterval;
//extern NSString * const TJPMetricsKeyHeartbeatTimeoutInterval;

// 网络性能指标
//extern NSString * const TJPMetricsKeyRTT;


// 流量统计指标
extern NSString * const TJPMetricsKeyBytesSend;
extern NSString * const TJPMetricsKeyBytesReceived;

// 数据包解析指标
extern NSString * const TJPMetricsKeyParsedPackets;
extern NSString * const TJPMetricsKeyParsedPacketsTime;
extern NSString * const TJPMetricsKeyParsedBufferSize;
extern NSString * const TJPMetricsKeyParseErrors;
extern NSString * const TJPMetricsKeyParsedErrorsTime;

// 负载统计指标
extern NSString * const TJPMetricsKeyPayloadBytes;
extern NSString * const TJPMetricsKeyParserResets;


// 消息统计指标
extern NSString * const TJPMetricsKeyMessageSend; // 消息发送总数
extern NSString * const TJPMetricsKeyMessageAcked; // 消息确认总数
extern NSString * const TJPMetricsKeyMessageTimeout; // 消息超时总数

// 消息类型统计指标
extern NSString * const TJPMetricsKeyControlMessageSend; // 控制消息发送数
extern NSString * const TJPMetricsKeyNormalMessageSend; // 普通消息发送数
extern NSString * const TJPMetricsKeyMessageRetried; // 消息重传总数


// 会话错误数和状态指标
extern NSString * const TJPMetricsKeyErrorCount; // 错误总数
extern NSString * const TJPMetricsKeySessionReconnects; // 会话重连次数
extern NSString * const TJPMetricsKeySessionDisconnects; // 会话断开次数


@interface TJPMetricsCollector : NSObject

//流量统计
@property (nonatomic, readonly) NSUInteger byteSend;
@property (nonatomic, readonly) NSUInteger byteReceived;



+ (instancetype)sharedInstance;


/// 计数器操作
- (void)incrementCounter:(NSString *)key;
/// 带增量的计数器
- (void)incrementCounter:(NSString *)key by:(NSUInteger)value;
/// 获取计数器
- (NSUInteger)counterValue:(NSString *)key;

- (void)addValue:(NSUInteger)value forKey:(NSString *)key;

/// 时间样本记录 (秒级单位)
- (void)addTimeSample:(NSTimeInterval)duration forKey:(NSString *)key;
- (NSTimeInterval)averageDuration:(NSString *)key;

/// 连接成功率
- (float)connectSuccessRate;
/// 平均往返时间
- (NSTimeInterval)averageRTT;
/// 丢包率
- (float)packetLossRate;

/// 指定状态平均处理时间
- (NSTimeInterval)averageStateDuration:(TJPConnectState)state;
/// 指定事件平均处理时间
- (NSTimeInterval)averageEventDuration:(TJPConnectEvent)event;


/// 错误记录
- (void)recordError:(NSError *)error forKey:(NSString *)key;
/// 重连错误
- (NSArray<NSDictionary *> *)recentErrors;

/// 记录事件
- (void)recordEvent:(NSString *)eventName withParameters:(NSDictionary *)params;
- (NSArray<NSDictionary *> *)recentEventsForName:(NSString *)eventName limit:(NSUInteger)limit;



@end

NS_ASSUME_NONNULL_END


Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@
//

#import "TJPMetricsCollector.h"
#import "TJPMetricsKeys.h"
#import <os/lock.h>

NSString * const TJPMetricsKeyConnectionAttempts = @"connection_attempts";
NSString * const TJPMetricsKeyConnectionSuccess = @"connection_success";
NSString * const TJPMetricsKeyHeartbeatSend = @"heartbeat_send";
NSString * const TJPMetricsKeyHeartbeatLoss = @"heartbeat_loss";
//NSString * const TJPMetricsKeyConnectionAttempts = @"connection_attempts";
//NSString * const TJPMetricsKeyConnectionSuccess = @"connection_success";

NSString * const TJPMetricsKeyHeartbeatRTT = @"heartbeat_rtt";
NSString * const TJPMetricsKeyHeartbeatInterval = @"heartbeat_interval";
NSString * const TJPMetricsKeyHeartbeatTimeoutInterval = @"heartbeat_timeout_interval";
//NSString * const TJPMetricsKeyHeartbeatSend = @"heartbeat_send";
//NSString * const TJPMetricsKeyHeartbeatLoss = @"heartbeat_loss";
//NSString * const TJPMetricsKeyHeartbeatRTT = @"heartbeat_rtt";
//NSString * const TJPMetricsKeyHeartbeatInterval = @"heartbeat_interval";
//NSString * const TJPMetricsKeyHeartbeatTimeoutInterval = @"heartbeat_timeout_interval";


NSString * const TJPMetricsKeyRTT = @"rtt";
//NSString * const TJPMetricsKeyRTT = @"rtt";

NSString * const TJPMetricsKeyBytesSend = @"bytes_send";
NSString * const TJPMetricsKeyBytesReceived = @"bytes_received";
Expand All @@ -34,27 +35,40 @@
NSString * const TJPMetricsKeyParserResets = @"parser_forced_resets";


NSString * const TJPMetricsKeyMessageSend = @"message_send_total";
NSString * const TJPMetricsKeyMessageAcked = @"message_acked_total";
NSString * const TJPMetricsKeyMessageTimeout = @"message_timeout_total";

// 消息类型统计指标
NSString * const TJPMetricsKeyControlMessageSend = @"control_message_send";
NSString * const TJPMetricsKeyNormalMessageSend = @"normal_message_send";
NSString * const TJPMetricsKeyMessageRetried = @"message_retried_total";


NSString * const TJPMetricsKeyErrorCount = @"error_count";
NSString * const TJPMetricsKeySessionReconnects = @"session_reconnects";
NSString * const TJPMetricsKeySessionDisconnects = @"session_disconnects";


@interface TJPMetricsCollector () {
os_unfair_lock _lock;
NSUInteger _bytesSend;
NSUInteger _bytesReceived;
}


/*
监控指标如下:
connection_attempts:连接尝试次数
connection_success:成功次数

heartbeat_send:心跳发送
heartbeat_loss:心跳丢失

*/
//指标数量监控
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *counts;

//时间数据存储
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSMutableArray<NSNumber *> *> *timeSeries;

//错误存储
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *errors;

//事件
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSMutableArray<NSDictionary *> *> *events;


@end

Expand All @@ -73,14 +87,38 @@ - (instancetype)init {
if (self = [super init]) {
_lock = OS_UNFAIR_LOCK_INIT;

// 初始化普通计数器
// 初始化计数器
_counts = [NSMutableDictionary dictionaryWithDictionary:@{
// 连接相关
TJPMetricsKeyConnectionAttempts: @0,
TJPMetricsKeyConnectionSuccess: @0,

// 心跳相关
TJPMetricsKeyHeartbeatSend: @0,
TJPMetricsKeyHeartbeatLoss: @0,

// 流量统计
TJPMetricsKeyBytesSend: @0,
TJPMetricsKeyBytesReceived: @0
TJPMetricsKeyBytesReceived: @0,

// 数据包解析
TJPMetricsKeyParsedPackets: @0,
TJPMetricsKeyParsedPacketsTime: @0,
TJPMetricsKeyParsedBufferSize: @0,
TJPMetricsKeyParseErrors: @0,
TJPMetricsKeyParsedErrorsTime: @0,
TJPMetricsKeyPayloadBytes: @0,
TJPMetricsKeyParserResets: @0,

// 消息统计
TJPMetricsKeyMessageSend: @0,
TJPMetricsKeyMessageAcked: @0,
TJPMetricsKeyMessageTimeout: @0,

// 错误和会话状态
TJPMetricsKeyErrorCount: @0,
TJPMetricsKeySessionReconnects: @0,
TJPMetricsKeySessionDisconnects: @0
}];

// 初始化时间序列
Expand All @@ -89,6 +127,8 @@ - (instancetype)init {
// 初始化字节计数器
_bytesSend = 0;
_bytesReceived = 0;

_events = [NSMutableDictionary dictionary];
}
return self;
}
Expand Down Expand Up @@ -124,6 +164,10 @@ - (NSUInteger)counterValue:(NSString *)key {
value = self->_bytesReceived;
}
else {
// 如果键不存在,添加一个默认值0
if (!self.counts[key]) {
self.counts[key] = @0;
}
value = [self.counts[key] unsignedIntegerValue];
}
}];
Expand Down Expand Up @@ -206,6 +250,76 @@ - (NSTimeInterval)averageEventDuration:(TJPConnectEvent)event {
}


#pragma mark - 错误记录
- (void)recordError:(NSError *)error forKey:(NSString *)key {
[self performLocked:^{
if (!self.errors) {
self.errors = [NSMutableArray array];
}

[self.errors addObject:@{
@"time": [NSDate date],
@"key": key ?: @"unknown",
@"code": @(error.code),
@"message": error.localizedDescription ?: @"No description"
}];

// 只保留最近的30条错误
if (self.errors.count > 30) {
[self.errors removeObjectsInRange:NSMakeRange(0, self.errors.count - 30)];
}

// 增加错误计数
[self incrementCounter:TJPMetricsKeyErrorCount];
}];
}

- (NSArray<NSDictionary *> *)recentErrors {
__block NSArray *result;
[self performLocked:^{
result = [self.errors copy];
}];
return result;
}

- (void)recordEvent:(NSString *)eventName withParameters:(NSDictionary *)params {
[self performLocked:^{
// 确保事件数组存在
NSMutableArray *eventArray = self.events[eventName];
if (!eventArray) {
eventArray = [NSMutableArray array];
self.events[eventName] = eventArray;
}

// 创建事件记录
NSMutableDictionary *eventRecord = [NSMutableDictionary dictionaryWithDictionary:params ?: @{}];
eventRecord[@"timestamp"] = [NSDate date];

// 添加事件
[eventArray addObject:eventRecord];

// 限制每种事件最多存储100条记录
if (eventArray.count > 100) {
[eventArray removeObjectsInRange:NSMakeRange(0, eventArray.count - 100)];
}
}];
}

- (NSArray<NSDictionary *> *)recentEventsForName:(NSString *)eventName limit:(NSUInteger)limit {
__block NSArray *result;
[self performLocked:^{
NSArray *events = self.events[eventName] ?: @[];
NSUInteger count = MIN(limit, events.count);
if (count == 0) {
result = @[];
return;
}
result = [events subarrayWithRange:NSMakeRange(events.count - count, count)];
}];
return result;
}



#pragma mark - 线程安全操作
- (void)performLocked:(void (^)(void))block {
Expand All @@ -215,4 +329,6 @@ - (void)performLocked:(void (^)(void))block {
}




@end
Loading