弱网优化

最近更新时间:2025-09-19 16:13:01

我的收藏

简介

本文介绍如何通过 COS SDK 使用 QUIC 协议访问 COS。

功能说明

针对弱网环境,COS SDK 已支持 QUIC 协议。QUIC 协议是一种基于 UDP 实现的低延迟高可靠通信协议,目前标准的 HTTP3 协议正是基于 QUIC 实现的。QUIC 支持 0-RTT 建立连接和无队头阻塞的多路复用,可以比较容易的在端侧实现用户态拥塞控制,更大限度地利用网络带宽进行实际的数据传输,在丢包率和网络延迟较高的弱网环境也可提供高质量的数据通信。同时,QUIC 还支持连接迁移,在移动端频繁切换网络的场景中,也可平滑过渡,保证网络不中断。
因此,如果您对上传下载等 COS 操作在弱网环境中的成功率、延迟较为敏感,您可以使用 QUIC 协议访问 COS。

前提条件

在开始执行操作前,您需要开通 EdgeOne 服务以及 QUIC 功能,并添加对应的 COS 域名。详细操作步骤如下:
1. 前往 EdgeOne 控制台 开通,具体操作请参见 开通 EdgeOne
2. 在 EdgeOne 控制台单击添加站点,添加业务方的加速域名。进入站点后进行域名管理 添加域名时请选择对象存储源站



3. 开启 EdgeOne 的 QUIC 功能,请参见 开启HTTP/3(QUIC)
4. 记录步骤2中的加速域名,该域名后续需要配置到 COS SDK 中。
注意:
EdgeOne 会产生一定的费用,详情请参见 EdgeOne 计费说明

操作步骤

步骤1:配置 QUIC 协议

Android
iOS
1. 在应用级别(通常是 App 模块下)的 build.gradle 中添加 QUIC 库依赖。
说明:
QUIC SDK 1.5.46已适配 16 KB page sizes,建议升级。
升级 QUIC SDK 时请同步升级 COS SDK 版本为 5.9.46及以上,否则可能存在兼容性问题。
dependencies {
...
// 增加此行
implementation 'com.qcloud.cos:quic:1.5.46'
}
2. 通过 COS SDK 中 CosXmlServiceConfig 进行自定义域名开启 QUIC
String region = "ap-beijing"; // 您的存储桶地域
String eoDomain = "exampledomain.com"; // eo 加速域名

CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder()
.setRegion(region)
.setHost(eoDomain) // 配置加速域名
.addNoSignHeaders("Host") // EO 转发请求时 host 会变化,此处需要避免 host 签名
.enableQuic(true) // 开启 QUIC
.builder();

CosXmlService cosXmlService = new CosXmlService(context, cosXmlServiceConfig,
credentialProvider);
1. 在 podfile 文件中添加 QUIC 库依赖。
pod 'QCloudQuic'
2. 通过 COS SDK 中 QCloudServiceConfiguration 进行自定义域名开启 QUIC
NSString * eoDomain = @"exampledomain.com";
QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];
configuration.enableQuic = YES; // 开启 Quic
configuration.appID = @"appId"; // 设置 APPId
configuration.signatureProvider = self;
QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] initWithLiteralURL:[NSURL URLWithString:eoDomain]]; // 配置加速域名
endpoint.useHTTPS = YES; // 使用 HTTPS
configuration.endpoint = endpoint;

步骤2:SDK 内配置协议切换

为了提高 SDK 请求的成功率以及节省成本,SDK 提供了协议切换策略的配置方法:
保守策略:先使用默认的 HTTPS 协议进行请求,网络失败后自动使用 QUIC 协议进行重试。
激进策略:先使用 QUIC 协议进行请求,网络失败后自动使用默认的 HTTPS 协议进行重试。
自定义策略:SDK 提供了配置请求网络协议的方法,可以灵活的在业务层控制请求和切换的逻辑(例如根据网络质量自动切换)。
不配置切换策略,则直接使用步骤一中的 QUIC 协议进行请求。
Android
iOS
通过 COS SDK 中 CosXmlServiceConfig 的 setNetworkSwitchStrategy 方法进行保守和激进策略的配置。
String region = "ap-beijing"; // 您的存储桶地域
String eoDomain = "exampledomain.com"; // eo 加速域名
// 激进策略
CosXmlServiceConfig.RequestNetworkStrategy aggressiveStrategy = CosXmlServiceConfig.RequestNetworkStrategy.Aggressive;
// 保守策略
CosXmlServiceConfig.RequestNetworkStrategy conservativeStrategy = CosXmlServiceConfig.RequestNetworkStrategy.Conservative;

CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder()
.setRegion(region)
.setHost(eoDomain) // 配置加速域名
.addNoSignHeaders("Host") // EO 转发请求时 host 会变化,此处需要避免 host 签名
.enableQuic(true) // 开启 QUIC
.setNetworkSwitchStrategy(aggressiveStrategy) // 配置切换策略为激进策略
//.setNetworkSwitchStrategy(conservativeStrategy) // 配置切换策略为保守策略
.builder();

CosXmlService cosXmlService = new CosXmlService(context, cosXmlServiceConfig,
credentialProvider);
通过请求基类 CosXmlRequest 的 setNetworkType 进行自定义策略的配置。
// 任何 CosXmlRequest 都支持这种方式,例如上传 PutObjectRequest、下载 GetObjectRequest、删除 DeleteObjectRequest 等
// 以下用上传进行示例
PutObjectRequest putRequest = new PutObjectRequest("examplebucket-1250000000", "exampleobject.txt", "本地文件路径");
// 自定义配置 QUIC 协议
putRequest.setNetworkType(CosXmlRequest.RequestNetworkType.QUIC);
// 自定义配置默认的 HTTPS 协议
// putRequest.setNetworkType(CosXmlRequest.RequestNetworkType.OKHTTP);
// 初始化 TransferConfig,这里使用默认配置,如果需要定制,请参考 SDK 接口文档
TransferConfig transferConfig = new TransferConfig.Builder().build();
// 初始化 TransferManager
TransferManager transferManager = new TransferManager(cosXmlService, transferConfig);
COSXMLUploadTask uploadTask = transferManager.upload(putRequest, null);
通过 COS SDK 中 QCloudServiceConfiguration 的 networkStrategy 方法进行保守和激进策略的配置。
NSString * eoDomain = @"exampledomain.com";
QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];
configuration.appID = @"appId"; // 设置 APPID
configuration.signatureProvider = self;
QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] initWithLiteralURL:[NSURL URLWithString:eoDomain]]; // 设置加速域名
endpoint.useHTTPS = YES; // 使用 https
// 配置加速域名
configuration.endpoint = endpoint;
// 配置切换策略为激进策略
configuration.networkStrategy = QCloudRequestNetworkStrategyAggressive;
// 配置切换策略为保守策略
// configuration.networkStrategy = QCloudRequestNetworkStrategyConservative;
// 开启 QUIC
configuration.enableQuic = YES;
[QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration];
[QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration:configuration];
注意:
EO 转发请求时 host 会变化,生成签名时需要指定Host不参与签名。如下所示:
- (void) signatureWithFields:(QCloudSignatureFields*)fileds
request:(QCloudBizHTTPRequest*)request
urlRequest:(NSMutableURLRequest*)urlRequst
compelete:(QCloudHTTPAuthentationContinueBlock)continueBlock
{
//这里同步从后台服务器获取临时密钥,强烈建议将获取临时密钥的逻辑放在这里,最大程度上保证密钥的可用性
//...
QCloudCredential* credential = [QCloudCredential new];

// 临时密钥 SecretId
// sercret_id 替换为用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capi
credential.secretID = @"SECRETID";
// 临时密钥 SecretKey
// sercret_key替换为用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capi
credential.secretKey = @"SECRETKEY";
// 临时密钥 Token
// 如果使用永久密钥不需要填入 token,如果使用临时密钥需要填入,临时密钥生成和使用指引参见 https://cloud.tencent.com/document/product/436/14048
credential.token = @"TOKEN";
/** 强烈建议返回服务器时间作为签名的开始时间, 用来避免由于用户手机本地时间偏差过大导致的签名不正确(参数 startTime 和 expiredTime 单位为秒)
*/
credential.startDate = [NSDate dateWithTimeIntervalSince1970:startTime]; // 单位是秒
credential.expirationDate = [NSDate dateWithTimeIntervalSince1970:expiredTime]];// 单位是秒

QCloudAuthentationV5Creator* creator = [[QCloudAuthentationV5Creator alloc]
initWithCredential:credential];
// 设置需要参与签名的 Header,不包含 Host 即可。
creator.shouldSignedList = @[@"Cache-Control", @"Content-Disposition", @"Content-Encoding", @"Content-Length", @"Content-MD5", @"Content-Type", @"Expect", @"Expires", @"If-Match" , @"If-Modified-Since" , @"If-None-Match" , @"If-Unmodified-Since" , @"Origin" , @"Range" , @"transfer-encoding",@"Pic-Operations",@"ci-process"];
// 注意 这里不要对 urlRequst 进行 copy 以及 mutableCopy 操作
QCloudSignature *signature = [creator signatureForData:urlRequst];
continueBlock(signature, nil);
}
通过设置基类 QCloudAbstractRequest 的 endpoint 进行自定义域名的配置。
QCloudPutObjectRequest* put = [QCloudPutObjectRequest new];
// 存储桶名称,由BucketName-Appid 组成,可以在 COS 控制台查看 https://console.cloud.tencent.com/cos5/bucket
put.bucket = @"examplebucket-1250000000";
// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"
put.object = @"exampleobject";
// 文件内容,可以传入NSData*或者NSURL*类型的变量
put.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];
// 自定义配置 QUIC 协议
put.networkType = QCloudRequestNetworkQuic;
[put setFinishBlock:^(id result, NSError *error) {
// result 包含响应的 header 信息
// 获取文件 crc64
NSString * crc64 = [[result __originHTTPURLResponse__].allHeaderFields valueForKey:@"x-cos-hash-crc64ecma"];
}];
[[QCloudCOSXMLService defaultCOSXML] PutObject:put];

示例工程

Android 示例 Demo 请参见 COS SDK 网络优化 Demo 下的 CosServiceFactory
iOS 示例 Demo 请参见 COS SDK 网络优化 Demo 下的 AppDelegate