Skip to content

Commit

Permalink
Merge pull request #386 from YangSen-qn/network_status_check
Browse files Browse the repository at this point in the history
Network status check & optimize upload progress & optimize some concurrent logic
  • Loading branch information
Mei-Zhao authored Feb 25, 2021
2 parents 9e8157a + 19cf5f1 commit ab024e2
Show file tree
Hide file tree
Showing 49 changed files with 870 additions and 290 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ jobs:
env:
QINIU_TEST_ENV: travis
run: |
xcodebuild test -workspace QiniuSDK.xcworkspace -scheme QiniuSDK_iOS -configuration Debug -destination 'platform=iOS Simulator,OS=14.2,name=iPhone 8 Plus' -enableCodeCoverage YES
xcodebuild test -workspace QiniuSDK.xcworkspace -scheme QiniuSDK_iOS -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 8 Plus' -enableCodeCoverage YES
xcodebuild test -workspace QiniuSDK.xcworkspace -scheme QiniuSDK_Mac -configuration Debug -destination 'platform=macOS,arch=x86_64'
bash <(curl -s https://codecov.io/bash)
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#Changelog
## 8.2.0(2021-02-20)
## 增加
- 增加网络监控功能,选择最优Host进行上传
- 处理上传进度不准确问题
- 优化日志统计

## 8.1.2(2021-01-18)
## 增加
- 区域查询采用SingleFlight模式
Expand Down
2 changes: 1 addition & 1 deletion Qiniu.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Qiniu'
s.version = '8.1.2'
s.version = '8.2.0'
s.summary = 'Qiniu Resource Storage SDK for iOS and Mac'
s.homepage = 'https://github.com/qiniu/objc-sdk'
s.social_media_url = 'http://weibo.com/qiniutek'
Expand Down
2 changes: 1 addition & 1 deletion QiniuDemo/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ source 'https://github.com/CocoaPods/Specs.git'
target "QiniuDemo" do
platform :ios, "7.0"

# pod 'Qiniu'
# pod 'Qiniu', '~> 8.1.1'
pod 'Qiniu',:path => '../'
end

Expand Down
4 changes: 2 additions & 2 deletions QiniuDemo/QiniuDemo/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ - (IBAction)uploadAction:(UIButton *)sender {
if (self.uploadState == UploadStatePrepare) {

#ifdef YourToken
// NSString *path = [[NSBundle mainBundle] pathForResource:@"UploadResource.dmg" ofType:nil];
NSString *path = [[NSBundle mainBundle] pathForResource:@"UploadResource_49M.zip" ofType:nil];
NSString *path = [[NSBundle mainBundle] pathForResource:@"UploadResource.dmg" ofType:nil];
// NSString *path = [[NSBundle mainBundle] pathForResource:@"UploadResource_49M.zip" ofType:nil];
[self uploadImageToQNFilePath:path];
[self changeUploadState:UploadStateUploading];
#else
Expand Down
62 changes: 62 additions & 0 deletions QiniuSDK.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions QiniuSDK/Collect/QNReportItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extern NSString *const QNReportRequestKeyUpTime;
extern NSString *const QNReportRequestKeyStatusCode;
extern NSString *const QNReportRequestKeyRequestId;
extern NSString *const QNReportRequestKeyHost;
extern NSString *const QNReportRequestKeyHttpVersion;
extern NSString *const QNReportRequestKeyRemoteIp;
extern NSString *const QNReportRequestKeyPort;
extern NSString *const QNReportRequestKeyTargetBucket;
Expand Down Expand Up @@ -88,6 +89,7 @@ extern NSString *const QNReportRequestKeySignalStrength;
extern NSString *const QNReportRequestKeyPrefetchedDnsSource;
extern NSString *const QNReportRequestKeyPrefetchedBefore;
extern NSString *const QNReportRequestKeyPrefetchedErrorMessage;
extern NSString *const QNReportRequestKeyNetworkMeasuring;


//MARK:-- 分块上传统计⽇志
Expand Down
2 changes: 2 additions & 0 deletions QiniuSDK/Collect/QNReportItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ - (NSString *)qualityResult{
NSString * const QNReportRequestKeyStatusCode = @"status_code";
NSString * const QNReportRequestKeyRequestId = @"req_id";
NSString * const QNReportRequestKeyHost = @"host";
NSString * const QNReportRequestKeyHttpVersion = @"http_version";
NSString * const QNReportRequestKeyRemoteIp = @"remote_ip";
NSString * const QNReportRequestKeyPort = @"port";
NSString * const QNReportRequestKeyTargetBucket = @"target_bucket";
Expand Down Expand Up @@ -203,6 +204,7 @@ - (NSString *)qualityResult{
NSString * const QNReportRequestKeyPrefetchedDnsSource = @"prefetched_dns_source";
NSString * const QNReportRequestKeyPrefetchedBefore = @"prefetched_before";
NSString * const QNReportRequestKeyPrefetchedErrorMessage = @"prefetched_error_message";
NSString * const QNReportRequestKeyNetworkMeasuring = @"network_measuring";

//MARK:-- 分块上传统计⽇志
NSString * const QNReportBlockKeyLogType = @"log_type";
Expand Down
10 changes: 7 additions & 3 deletions QiniuSDK/Common/QNAutoZone.m
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ - (instancetype)init{

- (QNZonesInfo *)getZonesInfoWithToken:(QNUpToken *)token {
if (token == nil) return nil;
[_lock lock];
[self.lock lock];
QNZonesInfo *zonesInfo = [_cache objectForKey:[token index]];
[_lock unlock];
[self.lock unlock];
return zonesInfo;
}

Expand Down Expand Up @@ -161,7 +161,7 @@ - (void)preQuery:(QNUpToken *)token
value.response = response;
value.metrics = metrics;
complete(value, nil);

[self destroyUploadRequestTransaction:transaction];
}];

Expand Down Expand Up @@ -198,13 +198,17 @@ - (QNRequestTransaction *)createUploadRequestTransaction:(QNUpToken *)token{
QNRequestTransaction *transaction = [[QNRequestTransaction alloc] initWithHosts:@[kQNPreQueryHost00, kQNPreQueryHost01]
regionId:QNZoneInfoEmptyRegionId
token:token];
[self.lock lock];
[self.transactions addObject:transaction];
[self.lock unlock];
return transaction;
}

- (void)destroyUploadRequestTransaction:(QNRequestTransaction *)transaction{
if (transaction) {
[self.lock lock];
[self.transactions removeObject:transaction];
[self.lock unlock];
}
}

Expand Down
1 change: 1 addition & 0 deletions QiniuSDK/Common/QNZoneInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern NSString *const QNZoneInfoEmptyRegionId;
@interface QNZoneInfo : NSObject

@property(nonatomic, assign, readonly)long ttl;
@property(nonatomic, assign, readonly)BOOL http3Enabled;
@property(nonatomic, strong, readonly)NSArray<NSString *> *domains;
@property(nonatomic, strong, readonly)NSArray<NSString *> *old_domains;

Expand Down
7 changes: 7 additions & 0 deletions QiniuSDK/Common/QNZoneInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ @interface QNZoneInfo()
@property(nonatomic, strong) NSDate *buildDate;

@property(nonatomic, assign) long ttl;
@property(nonatomic, assign)BOOL http3Enabled;
@property(nonatomic, strong)NSArray<NSString *> *domains;
@property(nonatomic, strong)NSArray<NSString *> *old_domains;

Expand Down Expand Up @@ -60,12 +61,18 @@ + (QNZoneInfo *)zoneInfoFromDictionary:(NSDictionary *)detailInfo {
regionId = QNZoneInfoEmptyRegionId;
}
long ttl = [[detailInfo objectForKey:@"ttl"] longValue];
BOOL http3Enabled = false;
if ([detailInfo[@"features"] isKindOfClass:[NSDictionary class]] &&
[detailInfo[@"features"][@"http3"] isKindOfClass:[NSDictionary class]]) {
http3Enabled = [detailInfo[@"features"][@"http3"][@"enabled"] boolValue];
}
NSDictionary *up = [detailInfo objectForKey:@"up"];
NSArray *domains = [up objectForKey:@"domains"];
NSArray *old_domains = [up objectForKey:@"old"];

NSMutableArray *allHosts = [NSMutableArray array];
QNZoneInfo *zoneInfo = [[QNZoneInfo alloc] init:ttl regionId:regionId];
zoneInfo.http3Enabled = http3Enabled;
if ([domains isKindOfClass:[NSArray class]]) {
zoneInfo.domains = domains;
[allHosts addObjectsFromArray:domains];
Expand Down
5 changes: 3 additions & 2 deletions QiniuSDK/Http/ConnectCheck/QNConnectChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
// Copyright © 2021 Qiniu. All rights reserved.
//

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

NS_ASSUME_NONNULL_BEGIN

@interface QNConnectChecker : NSObject

+ (BOOL)check;
+ (QNUploadSingleRequestMetrics *)check;

+ (void)check:(void(^)(BOOL isConnected))complete;
+ (BOOL)isConnected:(QNUploadSingleRequestMetrics *)metrics;

@end

Expand Down
42 changes: 21 additions & 21 deletions QiniuSDK/Http/ConnectCheck/QNConnectChecker.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,47 +27,52 @@ + (QNSingleFlight *)singleFlight {
return singleFlight;
}

+ (BOOL)check {
__block BOOL isConnected = false;
+ (BOOL)isConnected:(QNUploadSingleRequestMetrics *)metrics {
return metrics && ((NSHTTPURLResponse *)metrics.response).statusCode > 99;
}

+ (QNUploadSingleRequestMetrics *)check {
__block QNUploadSingleRequestMetrics *metrics = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[self check:^(BOOL isConnectedP) {
isConnected = isConnectedP;
[self check:^(QNUploadSingleRequestMetrics *metricsP) {
metrics = metricsP;
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return isConnected;
return metrics;
}

+ (void)check:(void (^)(BOOL isConnected))complete {
+ (void)check:(void (^)(QNUploadSingleRequestMetrics *))complete {
QNSingleFlight *singleFlight = [self singleFlight];

kQNWeakSelf;
[singleFlight perform:@"connect_check" action:^(QNSingleFlightComplete _Nonnull singleFlightComplete) {
kQNStrongSelf;

[self checkAllHosts:^(BOOL isConnected) {
singleFlightComplete(@(isConnected), nil);
[self checkAllHosts:^(QNUploadSingleRequestMetrics *metrics) {
singleFlightComplete(metrics, nil);
}];

} complete:^(id _Nullable value, NSError * _Nullable error) {
if (complete) {
complete([(NSNumber *)value boolValue]);
complete(value);
}
}];
}


+ (void)checkAllHosts:(void (^)(BOOL isConnected))complete {
+ (void)checkAllHosts:(void (^)(QNUploadSingleRequestMetrics *metrics))complete {

__block int completeCount = 0;
__block BOOL isCompleted = false;
__block BOOL isConnected = false;
kQNWeakSelf;
NSArray *allHosts = [kQNGlobalConfiguration.connectCheckURLStrings copy];
for (NSString *host in allHosts) {
[self checkHost:host complete:^(BOOL isHostConnected) {
[self checkHost:host complete:^(QNUploadSingleRequestMetrics *metrics) {
kQNStrongSelf;

BOOL isHostConnected = [self isConnected:metrics];
@synchronized (self) {
completeCount += 1;
}
Expand All @@ -84,30 +89,25 @@ + (void)checkAllHosts:(void (^)(BOOL isConnected))complete {
isCompleted = true;
}
}
complete(isConnected);
complete(metrics);
} else {
QNLogInfo(@"== check all hosts not completed totalCount:%d completeCount:%d", allHosts.count, completeCount);
}
}];
}
}

+ (void)checkHost:(NSString *)host complete:(void (^)(BOOL isConnected))complete {
+ (void)checkHost:(NSString *)host complete:(void (^)(QNUploadSingleRequestMetrics *metrics))complete {

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
request.URL = [NSURL URLWithString:host];
request.HTTPMethod = @"HEAD";
request.timeoutInterval = kQNGlobalConfiguration.connectCheckTimeout;

QNUploadSystemClient *client = [[QNUploadSystemClient alloc] init];
[client request:request connectionProxy:nil progress:nil complete:^(NSURLResponse * response, QNUploadSingleRequestMetrics * metrics, NSData * _Nullable data, NSError * error) {
if (response && [(NSHTTPURLResponse *)response statusCode] > 99) {
QNLogInfo(@"== checkHost:%@ result: true", host);
complete(true);
} else {
QNLogInfo(@"== checkHost:%@ result: false", host);
complete(false);
}
[client request:request connectionProxy:nil progress:nil complete:^(NSURLResponse *response, QNUploadSingleRequestMetrics * metrics, NSData * _Nullable data, NSError * error) {
QNLogInfo(@"== checkHost:%@ responseInfo:%@", host, response);
complete(metrics);
}];
}

Expand Down
37 changes: 37 additions & 0 deletions QiniuSDK/Http/NetworkStatus/QNNetworkStatusManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// QNNetworkStatusManager.h
// QiniuSDK
//
// Created by yangsen on 2020/11/17.
// Copyright © 2020 Qiniu. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface QNNetworkStatus : NSObject

/// 网速 单位:kb/s 默认:200kb/s
@property(nonatomic, assign, readonly)int speed;

@end


#define kQNNetworkStatusManager [QNNetworkStatusManager sharedInstance]
@interface QNNetworkStatusManager : NSObject


+ (instancetype)sharedInstance;

+ (NSString *)getNetworkStatusType:(NSString *)host
ip:(NSString *)ip;

- (QNNetworkStatus *)getNetworkStatus:(NSString *)type;

- (void)updateNetworkStatus:(NSString *)type
speed:(int)speed;

@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit ab024e2

Please sign in to comment.