简介
本文介绍如何通过优化网络访问线路提升上传下载等 COS 操作的成功率和速度。
功能说明
腾讯云在全球很多地区部署了存储中心,客户可以选择性地启用这些存储中心。但即便如此,还是无法避免一些终端用户与存储中心距离太远,以及部分客户的业务场景中存在需跨地区甚至跨海访问的场景。长距离的数据访问通常就意味着更长的网络链路和更大的传输时延,而且一旦中间某一个环节出现网络抖动、丢包等问题,就会拉低整条链路的访问速度和成功率。
针对长距离访问场景,网络链路过长导致的网络访问质量不佳问题,可以通过 COS 全球加速、EdgeOne 等将用户的请求转发给最靠近用户的边缘节点,就近接收用户的数据。再通过腾讯云打磨多年的加速网络,选择最优链路,将数据传送到存储中心。
前提条件
COS 全球加速。

EdgeOne + COS 全球加速。
1.1 前往 EdgeOne 控制台 开通,具体操作请参见 开通 EdgeOne。
1.2 在 EdgeOne 控制台单击添加站点,添加业务方的加速域名,进入站点后进行域名管理,添加域名时请选择对象存储源站和 S3兼容,在源站地址处填入 COS 全球加速域名(<BucketName-APPID>.cos.accelerate.myqcloud.com)。


1.3 开启 EdgeOne 的智能加速功能,请参见 智能加速。
1.4 获取步骤1.2中的加速域名,该域名后续需要配置到 COS SDK 中。
注意:
操作步骤
方式一:COS 全球加速
COS 全球加速功能的请求信息会通过腾讯云内网专线加速传输,不仅能实现请求的就近接入,还可以实现数据上传加速和下载加速。
通过 COS SDK 中 CosXmlServiceConfig 进行开启 COS 全球加速。
String region = "ap-beijing"; // 您的存储桶地域CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder().setRegion(region).setAccelerate(true) // 使用 COS 全球加速域名.builder();CosXmlService cosXmlService = new CosXmlService(context, cosXmlServiceConfig,credentialProvider);
通过 COS SDK 中 QCloudServiceConfiguration 进行开启 COS 全球加速。
QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];configuration.appID = @"appId"; // 设置 APP IDconfiguration.signatureProvider = self;QCloudCOSXMLEndPoint *endpoint = [[QCloudCOSXMLEndPoint alloc]init];endpoint.suffix = @"cos.accelerate.myqcloud.com"; // 设置全球加速域名endpoint.useHTTPS = YES; // 使用 httpsconfiguration.endpoint = endpoint;
在浏览器端,使用 JavaScript SDK 实例化时,配置 UseAccelerate: true 可指定使用全球加速上传/下载。
var cos = new COS({UseAccelerate: true, // 指定 true,使用全球加速域名请求});
方式二:EdgeOne + COS 全球加速
该方式结合了 EdgeOne 和 COS 全球加速的优点:EdgeOne 边缘节点覆盖广,COS 全球加速内网加速回源。
通过 COS SDK 中 CosXmlServiceConfig 进行加速域名的配置。
String region = "ap-beijing"; // 您的存储桶地域String eoDomain = "exampledomain.com"; // eo 加速域名CosXmlServiceConfig cosXmlServiceConfig = new CosXmlServiceConfig.Builder().setRegion(region).setHost(eoDomain) // 配置加速域名.addNoSignHeaders("Host") // EO 转发请求时 host 会变化,此处需要避免 host 签名.builder();CosXmlService cosXmlService = new CosXmlService(context, cosXmlServiceConfig,credentialProvider);
通过 COS SDK 中 QCloudServiceConfiguration 进行加速域名的配置。
NSString * eoDomain = @"exampledomain.com";QCloudServiceConfiguration* configuration = [QCloudServiceConfiguration new];configuration.appID = @"appId"; // 设置 APP IDconfiguration.signatureProvider = self;QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] initWithLiteralURL:[NSURL URLWithString:eoDomain]]; // 设置加速域名endpoint.useHTTPS = YES; // 使用 httpsconfiguration.endpoint = endpoint;
1. 在浏览器端上传 EdgeOne 域名,需要到 EdgeOne 设置请求固定返回 CORS 跨域头,其中对 Access-Control-Allow-Headers 头部设置为 Authorization,x-cos-security-token,x-cos-sdk-retry,Cache-Control,Content-Type,Content-Length,Content-Md5

2. 在浏览器端,使用 JavaScript SDK 实例化时,使用 Domain 参数指定走 EO 域名上传下载。
var cos = new COS({Domain: 'edgeone.example.com', // 指定请求域名为 EdgeOne 的域名。ForceSignHost: false, // 由于实际请求的域名和回源域名不一致,需要指定不签 Host 头。Host});
方式三:SDK 内配置线路切换
为了提高 SDK 请求的成功率以及节省成本,SDK 提供了线路切换策略的配置方法:
保守策略:先使用 COS 默认线路进行请求,网络失败后自动使用加速线路进行重试。
激进策略:先使用加速线路进行请求,网络失败后自动使用 COS 默认线路进行重试。
自定义策略:SDK 提供了配置请求网络线路的方法,可以灵活的在业务层控制请求和切换的逻辑(例如根据网络质量自动切换)。
不配置切换策略,则直接使用方式一和方式二中的加速线路进行请求。
通过 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 签名.setNetworkSwitchStrategy(aggressiveStrategy) // 配置切换策略为激进策略//.setNetworkSwitchStrategy(conservativeStrategy) // 配置切换策略为保守策略.builder();CosXmlService cosXmlService = new CosXmlService(context, cosXmlServiceConfig,credentialProvider);
通过请求基类 CosXmlRequest 的 setHost 进行自定义策略的配置。
// 任何CosXmlRequest都支持这种方式,例如上传PutObjectRequest、下载GetObjectRequest、删除DeleteObjectRequest等// 以下用上传进行示例PutObjectRequest putRequest = new PutObjectRequest("examplebucket-1250000000", "exampleobject.txt", "本地文件路径");String eoDomain = "exampledomain.com"; // eo 加速域名// 自定义配置具体的请求网络线路,设置null则走默认的COS域名线路putRequest.setHost(eoDomain);// 初始化 TransferConfig,这里使用默认配置,如果需要定制,请参考 SDK 接口文档TransferConfig transferConfig = new TransferConfig.Builder().build();// 初始化 TransferManagerTransferManager 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"; // 设置 APP IDconfiguration.signatureProvider = self;QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] initWithLiteralURL:[NSURL URLWithString:eoDomain]]; // 设置加速域名endpoint.useHTTPS = YES; // 使用 https// 配置加速域名configuration.endpoint = endpoint;// 配置切换策略为激进策略configuration.networkStrategy = QCloudRequestNetworkStrategyAggressive;// 配置切换策略为保守策略// configuration.networkStrategy = QCloudRequestNetworkStrategyConservative;[QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration];[QCloudCOSTransferMangerService registerDefaultCOSTransferMangerWithConfiguration:configuration];
注意:
EO 转发请求时 host 会变化,生成签名时需要指定 Host 不参与签名。如下所示:
- (void) signatureWithFields:(QCloudSignatureFields*)filedsrequest:(QCloudBizHTTPRequest*)requesturlRequest:(NSMutableURLRequest*)urlRequstcompelete:(QCloudHTTPAuthentationContinueBlock)continueBlock{//这里同步从后台服务器获取临时密钥,强烈建议将获取临时密钥的逻辑放在这里,最大程度上保证密钥的可用性//...QCloudCredential* credential = [QCloudCredential new];// 临时密钥 SecretId// sercret_id 替换为用户的 SecretId,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capicredential.secretID = @"SECRETID";// 临时密钥 SecretKey// sercret_key替换为用户的 SecretKey,登录访问管理控制台查看密钥,https://console.cloud.tencent.com/cam/capicredential.secretKey = @"SECRETKEY";// 临时密钥 Token// 如果使用永久密钥不需要填入 token,如果使用临时密钥需要填入,临时密钥生成和使用指引参见 https://cloud.tencent.com/document/product/436/14048credential.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];// 设置自定义域名NSString * eoDomain = @"exampledomain.com";QCloudCOSXMLEndPoint* endpoint = [[QCloudCOSXMLEndPoint alloc] initWithLiteralURL:[NSURL URLWithString:eoDomain]]; // 设置加速域名put.endpoint = endpoint;// 存储桶名称,由 BucketName-Appid 组成,可以在 COS 控制台查看 https://console.cloud.tencent.com/cos5/bucketput.bucket = @"examplebucket-1250000000";// 对象键,是对象在 COS 上的完整路径,如果带目录的话,格式为 "video/xxx/movie.mp4"put.object = @"exampleobject";// 文件内容,可以传入 NSData*或者 NSURL*类型的变量put.body = [@"testFileContent" dataUsingEncoding:NSUTF8StringEncoding];[put setFinishBlock:^(id result, NSError *error) {// result 包含响应的 header 信息// 获取文件 crc64NSString * 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。