高德文件直传能力建设

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储OSS,敏感数据保护2.0 200GB 1年
对象存储 OSS,内容安全 1000 次 1年
简介: 1.文件上传之痛在没有这个基础能力之前,客户端要实现文件上传有这么几种方式:业务服务端通过对接OSS SDK搭建文件上传的能力,通过高德网关(或SNS网关)暴露对端的接口实现文件上传客户端直接本地写死AK、SK对接OSS的SDK实现文件上传这两种方式都有很明显的弊端。网关在设计上本身不适合做大文件的上传,影响网关的吞吐量,容易给网关带来很大的稳定性风险。另外对于业务服务内部也是不友好的,大文件长时

1.文件上传之痛

在没有这个基础能力之前,客户端要实现文件上传有这么几种方式:

  1. 业务服务端通过对接OSS SDK搭建文件上传的能力,通过高德网关(或SNS网关)暴露对端的接口实现文件上传
  2. 客户端直接本地写死AK、SK对接OSS的SDK实现文件上传

这两种方式都有很明显的弊端。

  1. 网关在设计上本身不适合做大文件的上传,影响网关的吞吐量,容易给网关带来很大的稳定性风险。另外对于业务服务内部也是不友好的,大文件长时间阻塞线程,造成系统吞吐量下降,如果是C端大流量应用的话,这个影响更加明显,高耗时和低耗时接口应该做隔离。
  2. 容易造成AK泄漏,有很大的安全性风险。OSS资源一般都是后端维护的资源,把密钥暴露给前端,也是不太合理的做法
  3. 同时也无法做大文件上传,断点续传这样的能力

高德作为一个日活过亿的国民级APP,有很多场景都有文件上传的诉求,每天都在经历着类似如上的各种问题,有没有一种更高效的方式实现文件上传,为业务方提效?

2.方案调研

经过调研发现,OSS提供了一种临时授权的方案,可以让客户端在保证安全的情况下和OSS做直连,这样就不需要服务端提供上传接口同时客户端很容易使用OSS提供的大文件上传、断点续传等能力。方案如下图所示:

您可以通过STS服务给其他用户颁发一个临时访问凭证。该用户可使用临时访问凭证在规定时间内访问您的OSS资源。临时访问凭证无需透露您的长期密钥,使您的OSS资源访问更加安全。

这个方案的优点也很明显:

  • 服务端持有AK,加密存储防止泄漏
  • 服务端下发临时Token,安全性更高
  • 客户端直连OSS,避免服务端性能瓶颈,可以很方便做大文件上传,断点续传等能力

这个方案里最大的不确定性就是在诺曼底走通STS认证的完整流程。刚入职不太清楚内部申请阿里云资源都是通过诺曼底,就直接在阿里云上申请,一路走下来很顺利。后来发现需要在诺曼底申请资源,才发现这里面的坑相当多,各种账号权限的不通,花了整整一周才搞定整个流程。

根据踩过的坑,整理了一个OSS对接STS认证模式接入的文档。有需要的可以看下(看过的都说靠谱^^)

参见:OSS对接-STS认证模式接入参考文档 

3.设计目标

满足各多场景的用户资源(视频、图片等)上传诉求,为客户端以及业务服务提供统一的平台化文件上传服务。架构设计上联合客户端,对上层业务屏蔽资源上传的技术细节,提供统一的上传方式,同时平台能力上提供断点续传、回调通知等系统能力,以及 提供业务维度的准入管控、资源管控等资源维护能力。

4.方案设计

4.1.方案概述

我们需要搭建一个文件上传的服务,处理STS授权相关的事情,比如临时token的生成、下发以及缓存更新的事情。还需要搭建一个文件上传的后台,进行业务方注册申请,oss相关的配置。后期提供基于bizId的统计分析功能。

对端SDK能力的支持,提供多种上传下载的能力包括

  • 简单上传
  • 断点续传上传及下载
  • 分片上传

4.2.上下游整体链路

主要分为三大部分:

  • 客户端基础SDK。主要做凭证获取、Token过期自动刷新、断连重试、文件上传下载等能力
  • 文件上传服务。承载凭证下发的核心能力,通过读取业务配置,从OSS获取临时Token,过期自动刷新,保证Token的可用性
  • 服务管控平台。主要做管控相关的能力,业务方的接入、配置上下线。对接MTEE,风险挖掘识别。

4.3.文件上传交互流程

一个文件上传的完整流程。这个流程是基础SDK和服务端的交互流程,对于业务客户端来说是无感的。

4.4.AK托管如何保证安全性?

在这套方案里,需要业务方申请OSS资源,提供AK、SK给到文件服务进行配置,分配对应的bizId。所以需要保证AK的安全性。集团有提供无AK化托管的方案。但是经过调研发现没法满足当前的场景。集团无AK化方案只能跟应用绑定,但是在文件服务里,资源都是业务方申请的,绑定的应用各不相同,文件服务也不好提供统一的应用供业务方绑定。所以这条路走不通。最终采用最常规的方案,利用KeyCenter实现AK的托管。

业务方申请配置中保存ak的密文,在获取token时调用KeyCenter接口解密获取明文,再调用OSS的认证接口获取临时token。实际测试发现KeyCenter解密的耗时在200ms左右,对接口的吞吐量影响很大。因此做了一些优化:在项目启动时,通过对密文解密,生成明文AK,加载到内存中,后续使用ak时直接从内存中获取。大大降低了接口RT。

4.5.临时Token缓存方案设计

获取临时Token,OSS限制了一个账号每秒最多只能请求100次。如果客户端频繁请求临时令牌,会导致oss封禁接口。

解决方案,服务端缓存token。缓存过期时间可配置,要比真实的过期时间早过期。这样可以保证客户端拿到的token的最小可用时间(比如10分钟)。同时为了避免缓存失效时所有请求都打到OSS的情况,加入了分布式锁的控制,同一时刻只能有一个请求生成临时token,其他请求排队等待。

4.6. 性能方面的一些优化

其实这些优化点在上面都已经提到了。主要有三点

  • 为了解决AK密文解密耗时的问题,采用项目启动时并发解密获取明文AK、SK,常驻内存。
  • 为了减少缓存Token过期重新获取临时的Token带来的毛刺波动,采用定时任务异步刷新Token,这样能保证所有请求都能从内存直接获取临时Token,能保证很好的接口响应表现
  • 获取临时Token时的分布式锁控制,避免触发OSS的限流规则。

通过以上的动作,客户端SDK获取Token就变成了纯内存的查询操作,RT是非常低的。

4.7 其他概念介绍

在设计上为每个租户生成一个bizId,bizId对应子账号、角色、权限、endpoint、bucket这些概念,他们之间的关系如下图所示

每个账号生成临时token都可以设置单独的权限policy(比如控制生成的Token只有可读、可写,某一目录的权限),在进行业务配置时可以指定。配置示例如:

"policy":{
            "Version":"1",
            "Statement":[
                {
                    "Effect":"Allow",
                    "Action":"oss:*",
                    "Resource":[
                        "acs:oss:*:*:amap-architecture",
                        "acs:oss:*:*:amap-architecture/*"
                    ]
                }
            ]
        },
AI 代码解读

CDN加速

对于大流量的场景,需要配置CDN加速访问,具体可参考

https://yuque.antfin.com/eio17z/iq5svr/ar43cd 《如何开启CDN加速》

4.8. 压测数据分享

单机(4C8G)可承载2500QPS,RT在55ms以内,CPU利用率峰值36%

https://yuque.antfin.com/eio17z/iq5svr/xgfuxb 《压测报告》

5. 说了这么多,如何使用呢

详细的使用文档见:https://yuque.antfin.com/docs/share/3e28b8c5-5ce5-4025-834f-519cb849670f?# 《OSS直传-业务接入流程》

总结一下接入步骤:

  • 在诺曼底完成账号申请,资源申请
  • 提供资源信息由平台分配bizId(目前通过发邮件申请,后期会提供后台能力自行申请创建)
  • 拿到bizId,发起调用。
  • 客户端SDK接入的流程

客户端调用代码示例:

重要提示:由于文件在OSS服务端是通过 ossSaveDir + 本地文件名的方式存储的,相同的文件名会覆盖,因此接入前辛苦业务方确认下,是否需要保证文件的唯一性。可以在 ossSaveDir 中加入类似UID,或者时间戳来保证文件的唯一性。

上传方案一:AJX切面接入

/// 上传
const uploadObj = {bizId: (申请的bizId,例如: 111000_fileservice-read_aos_c1), fileLocalPath: (本地文件绝对路径,例如: file:///sdcard/xxx/yyy/demo.txt), ossSaveDir: (远端存储路径,以"/"结尾,例如:a/b/)};
requestId = natives.oss.uploadFile(uploadObj, (error, result) => {
              if (result) {
                const res = JSON.parse(result);
                ajx.app.toast(`result:${res.msg}`)
              }
            }, (progress) => {
              const prog = JSON.parse(progress);
              if (prog) {
                ajx.app.toast(`${prog.progress}`)
              }
            });

/// 取消上传
natives.oss.cancel(requestId);
AI 代码解读

上传方案二:Native接入

/// 1、创建upload对象
GDOSSUploadRequest *uploadRequest = [[GDOSSUploadRequest alloc] init];

/// 2、申请的bizId,例如:111000_fileservice_aos_c1
uploadRequest.bizId = @"111000_fileservice_aos_c1";

/// 3、本地文件绝对路径
uploadRequest.fileLocalPath = [[NSBundle mainBundle] pathForResource:@"LargeFile" ofType:@"zip"];

/// 4、远端存储路径,以"/"结尾,例如:a/b/
uploadRequest.ossSaveDir = @"a/b/";

/// 5、上传
NSString *requestId = [AMapNetworkService uploadWithRequest:uploadRequest progress:^(NSInteger progress, int64_t current, int64_t total) {
        
} completion:^(GDOSSUploadResponse * _Nonnull response) {

}];

/// 取消上传
[AMapNetworkService cancelOSSRequestWithId:requestId];
AI 代码解读

注意:如果上传的文件名有特殊字符(空格,加号等),返回的 objectName 也会带有特殊字符。业务方自己拼接 URL 做下载时,需对 URL 进行 urlEncode 处理,否则 URL 无效。

下载方案一:AJX切面接入

/// 下载
const downloadObj = {objectName`下载文件名`localPath`下载文件的绝对路径.文件后缀名,例如:file://documents/oss/media/tmp/a.file`bizId`申请的bizId,例如:111000_fileservice_aos_c1`};
downloadTaskId = natives.oss.downloadFile(downloadObj, (error, result) => {
        						if (error) {
           						ajx.log.print(error);
        						} else {
             						if (result) {
                   				 const res = JSON.stringify(result);
                    			 ajx.log.print(`${downloadTaskId} result:${res}`);
                				} else {
                   				 ajx.log.print(`download result is empty`)
              		 		  }
       					 		}	
        				  }, (progress) => {
            				if (progress) {
                			ajx.log.print(JSON.stringify(progress))
            				}
        					});
/// 取消下载
natives.oss.cancel(downloadTaskId);
AI 代码解读

下载方案二:img标签接入

/// img标签加载图片
<img src="oss://111000_fileservice_aos_c1/test/33333.jpg" style={{ 'width'"500px"'height'"500px"'border-radius''70px' }} />
AI 代码解读

下载方案三:Native接入

/// 1、创建download对象
GDOSSDownloadRequest *request = [[GDOSSDownloadRequest alloc] init];

/// 2、申请的bizId,例如:111000_fileservice_aos_c1
request.bizId = @"111000_fileservice-read_aos_c1";

/// 3、下载的文件名
request.objectName = [NSString stringWithFormat:@"test/bigfile.zip"];

/// 4、下载的本地绝对路径
request.destinationPath = @"AbsolutePath/bigfile_0.zip";

/// 5、下载
NSString *downloadRequestId = [AMapNetworkService downloadWithRequest:request progress:^(NSInteger progress, int64_t current, int64_t total) {
        
} completion:^(GDOSSDownloadResponse * _Nonnull response) {
        
}];

/// 取消下载
[AMapNetworkService cancelOSSRequestWithId:downloadRequestId];
AI 代码解读

就先介绍到这里。

整理了一些常见的问题,需要时自取

https://yuque.antfin.com/docs/share/b047d959-7adc-46bb-a47d-c5514fde4050?# 《OSS直传能力接入常见问题》

6.接入情况

目前已有足迹、停车点记录、用反、评论,趣游等九个业务方接入,每日业务传文件量5w+。欢迎更多的业务场景接入,为大家提效。

7.后期规划

  • 自动化接入平台建设。目前申请流程比较繁琐,需要很多道申请审批流程,配置也较多,很容易出错。终极目标是提供自动化接入的能力,把诺曼底上的申请流程实现自动化对接,让业务方的申请过程变得丝滑
  • web端文件上传能力建设。目前的上传支持AMAP里的上传诉求,对于WEB端的上传还不支持,后期需要补齐这一块能力
  • 统计分析&风控能力。提供基于bizId 维度的风控配置、统计分析等能力。

开发团队:

移动架构部:郝仁杰、呼唤、陈腾蛟、任涛

技术服务平台自主出行服务端:魏国兵、闻钟

有相关业务场景接入,欢迎加钉钉群沟通: 33253097

相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
bludy
+关注
目录
打赏
0
0
1
1
0
分享
相关文章
vue3用户权限管理(路由控制等)1
在前端开发的过程中,我们需要做前端的权限管理,我们需要根据后端提供的信息来控制权限,这时候就需要根据用户的操作来进行权限控制了。逻辑稍微有一点绕,多理解就好了。
356 0
【秒懂·云原生】微服务篇 —— 微服务究竟是什么?
【秒懂·云原生】微服务篇 —— 微服务究竟是什么?
2018 0
【秒懂·云原生】微服务篇 —— 微服务究竟是什么?
阿里云资深架构师经验分享——DevSecOps最佳实践
本文将分享阿里云在DevSecOps中设计环节的实践经验,希望能够让大家理解阿里云是如何保障产品安全水位,并希望这些经验能够帮助到正在尝试落地DevSecOps解决方案的企业。
753 167
阿里云资深架构师经验分享——DevSecOps最佳实践
【阿里云弹性计算】阿里云 ECS 性能优化秘籍:提升应用响应速度与资源利用率
【5月更文挑战第22天】阿里云ECS优化涉及实例规格选择、OS与应用配置、网络配置、存储优化及数据库连接池管理。合理挑选CPU和内存,关闭无关服务,利用EIP和负载均衡优化网络,选择合适存储类型,并通过监控工具进行性能分析和压力测试,以提升响应速度,优化资源利用率,降低成本,增强企业竞争力。示例展示了Java数据库连接池配置优化。通过持续探索和实践,可最大化发挥ECS潜力。
414 7
【AI系统】推理系统介绍
推理系统是一种专门用于部署和执行神经网络模型预测任务的AI系统,类似于Web服务或移动端应用,但专注于AI模型的部署与运行。它支持将模型部署到云端或边缘端,处理用户请求。本文介绍了训练与推理的基本流程、两者差异、推理系统的优化目标及挑战,并对比了推理系统与推理引擎的流程结构,强调了设计推理系统时需考虑的优化目标,如灵活性、延迟、吞吐量、高效率、扩展性和可靠性。同时,文章还讨论了推理系统与推理引擎的区别,帮助读者深入了解推理引擎的核心技术。
312 5
【2023五福】创新科技与传统年俗的有机融合 - AI 年画
23 年兔年,五福项目将传统的写福字升级成了年画,用户通过绘制兔子轮廓可以得到活动的兔子,同时由 AI 生成对应的兔子年画,整个过程给用户带来很强的惊喜感,同时将具有传统氛围的年画与科技感拉满的 AI 作图有机结合,为大家带来全新的年俗体验。AI 年画作为 23 兔年五福的创新项目,在玩法和技术方案上都采用全新的实现,前后端技术、AI 算法深度,以及美术互动等深度协同,实现了玩法了技术的双创新,最
【2023五福】创新科技与传统年俗的有机融合 - AI 年画
常用的相似度度量总结:余弦相似度,点积,L1,L2
相似性度量在机器学习中起着至关重要的作用。这些度量以数学方式量化对象、数据点或向量之间的相似性。理解向量空间中的相似性概念并采用适当的度量是解决广泛的现实世界问题的基础。本文将介绍几种常用的用来计算两个向量在嵌入空间中的接近程度的相似性度量。
1078 1
开源微服务编排框架:Netflix Conductor
本文主要介绍netflix conductor的基本概念和主要运行机制。
开源微服务编排框架:Netflix Conductor
[√]cocos2dx接入firebase后,点击消息通知栏闪退渲染异常
[√]cocos2dx接入firebase后,点击消息通知栏闪退渲染异常
202 0
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问