统一存储接入方案分析

原创阿虎
发布于:2021-02-01 
标签: 

背景

在项目的实施过程中,遇到越来越多的第三方私有或公有化存储云服务,有阿里OSS、华为云OBS、七牛云Kodo等,各存储厂商对接标准备和SDK尽不相同,这对项目的实施和运维带来了很大的挑战,所以急需为各项目开发一套统一的存储接入标准,屏蔽各厂商接入差异,增强业务快速实施及产品化的能力。

项目痛点分析

目的

现市场上主要对象存储服务类型

他们有一个共同的特性,都兼容亚马逊S3存储协议

华为云存储

权限机制

Java SDK上传

TempTokenDO tempTokenDO = getTempToken();
ObsClient obsClient = new ObsClient(tempTokenDO.getAk(), tempTokenDO.getSk(), tempTokenDO.getSt(), thirdpartyEndpoint);
 PutObjectResult putObjectResult = obsClient.putObject(bucketName, key, fileInputStream);

//获取token
 private TempTokenDO getTempToken(String ak, String sk){

        StopWatch sw = new StopWatch();
        TempTokenDO tempTokenDO = null;
        try{
            sw.start("getTempToken");
            ICredential auth = new GlobalCredentials().withAk(ak).withSk(sk);
            IamClient client = IamClient.newBuilder().withCredential(auth).withRegion(IamRegion.valueOf(this.region)).build();
            CreateTemporaryAccessKeyByTokenRequest request = new CreateTemporaryAccessKeyByTokenRequest();
            CreateTemporaryAccessKeyByTokenRequestBody body = new CreateTemporaryAccessKeyByTokenRequestBody();
            List<TokenAuthIdentity.MethodsEnum> listIdentityMethods = new ArrayList<>();
            listIdentityMethods.add(TokenAuthIdentity.MethodsEnum.fromValue("token"));
            TokenAuthIdentity identityAuth = new TokenAuthIdentity();
            identityAuth.withMethods(listIdentityMethods);
            TokenAuth authBody = new TokenAuth();
            authBody.withIdentity(identityAuth);
            body.withAuth(authBody);
            request.withBody(body);

            CreateTemporaryAccessKeyByTokenResponse response = client.createTemporaryAccessKeyByToken(request);
            Credential credential = response.getCredential();
            if(null == credential){
                throw new BaseException(StorageMessage.B4101);
            }
            tempTokenDO = new TempTokenDO().setAk(credential.getAccess()).setSk(credential.getSecret())
                    .setSt(credential.getSecuritytoken()).setExpiresAt(credential.getExpiresAt());

        }catch (ServiceResponseException e) {
            log.error("获取临时凭证异常:"+e.getMessage(), e);
            throw new BaseException(StorageMessage.B4101, e);
        }finally {
            if(sw.isRunning()){
                sw.stop();
            }
            log.debug("sw_getTempToken:"+sw.toString());
        }
        return tempTokenDO;

    }

JS SDK上传

阿里云存储

权限机制

file

Java SDK上传

JS SDK上传

七牛云存储

Kodo 是七牛云提供的高可靠、强安全、低成本、可扩展的存储服务。可通过控制台、API、SDK 等方式简单快速地接入七牛存储服务,实现海量数据的存储和管理。对文件下载进行加速,智能多媒体 人脸技术、场景物体识别、OCR 文字识别和内容审核等

请参阅对象存储文档:https://developer.qiniu.com/kodo

接入流程

注册七牛云帐号-->创建空间-->绑定域名-->上传下载等资源管理

参考文档:https://developer.qiniu.com/kodo/1233/console-quickstart

空间(bucket)

空间是资源的组织管理单位,一个资源必然位于某个空间中。可以为每个空间设置一系列的属性,以对资源提供合理的管理动作

公开空间:可通过文件对象的 URL 直接访问。
私有空间:文件对象的访问则必须获得拥有者的授权才能访问。

空间设置功能

编程模型

file

安全机制

七牛云存储服务的过程中,需要考虑安全机制的三种场景对应三种凭证:

https://github.com/qiniu/java-sdk/blob/master/src/main/java/com/qiniu/util/Auth.java

推荐的安全模型如下所示:
file

上传资源

https://developer.qiniu.com/kodo/1234/upload-types
上传文件的名称中,不支持\0字符,若文件名中存在\0字符,则会返回 400 Bad Request 和 error message “key must not contain null byte”。
上传文件名 utf-8 编码字符,长度不超过 750 字节 。

下载资源

https://developer.qiniu.com/kodo/1232/download-process

您也可以为某特定空间,绑定自定义域名,例如i.example.com,您就可以通过以下 URL 访问同样的资源:

http://i.example.com/resource/flower.jpg

当您将空间设置成私有时,必须获得授权,才能对空间内的资源进行访问。
私有资源下载是通过HTTP GET的方式访问特定的 URL。私有资源URL与公开资源URL相比只是增加了两个参数e和token,分别表示过期时间和下载凭证。一个完整的私有资源 URL 如下所示:

http://<domain>/<key>?e=<deadline>&token=<downloadToken>

SDK

https://developer.qiniu.com/sdk#official-sdk

file

AWS S3 兼容

为了使众多基于AWS S3接口协议开发的各类应用及服务能够轻便的接入七牛对象存储,七牛对象存储兼容了AWS S3常用接口。接口的具体兼容情况,在下文中做了详细叙述。

七牛云存储兼容S3协议接口,是为了尽可能的方便基于 AWS S3 而开发的应用接入到七牛对象存储。如果您刚刚开始着手开发新的应用,为了更好的使用七牛对象存储丰富的产品功能,更推荐使用原生接口进行开发。

实用工具

https://developer.qiniu.com/sdk#official-tool

file

实例演示

后端上传

https://github.com/qiniu/java-sdk


@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest
@Slf4j
class UploadTest {
/**
 * 空间
 */
private static String bucketName;

/**
 * 下载自定义域名
 */
private String endpoint;

/**
 * 上传管理器
 */
UploadManager uploadManager;

/**
 * 空间管理器
 */
private BucketManager bucketManager;

/**
 * 验证管理器
 */
Auth auth = null;

@BeforeAll
void init(){
    this.bucketName = "hushow";
    this.endpoint = "http://qnvs9yac3.hn-bkt.clouddn.com";
    String accessKey = "PheIieVFKcYRmdn6mFDNZ9uIO6NJN36Q4fM1HudC";
    String secretKey = "OZWR8o20c0OrLryl2TJoH8JAu8LifyTo3rto-OjC";
    this.auth = Auth.create(accessKey, secretKey);
    this.uploadManager = new UploadManager(new Configuration());
    bucketManager = new BucketManager(auth, new Configuration());
}

@Test
void uploadTest() throws Exception{
    String token = auth.uploadToken(bucketName);
    String fileUrl = "classpath:images/1.jpg";
    File file = ResourceUtils.getFile(fileUrl);
    String key = file.getName();
    Response response = uploadManager.put(file, key, token);
    log.info("response:{}", JSONObject.toJSONString(response));
    Assertions.assertTrue(response.isOK(), "上传失败");
}

@Test
void deleteTest() throws Exception{
    String key = "1.jpg";
    Response response = bucketManager.delete(bucketName, key);
    log.info("response:{}", JSONObject.toJSONString(response));
    Assertions.assertTrue(response.isOK(), "删除失败");
}

}


上传结果响应
```json
{
    "address": "upload-z2.qiniup.com/14.29.110.7:443", 
    "duration": 2.352, 
    "info": "POST https://upload-z2.qiniup.com/  
{ResponseInfo:com.qiniu.http.Response@1f9c6ea,status:200, reqId:Y40AAADoLc02HWAW, xlog:X-Log, xvia:, adress:upload-z2.qiniup.com/14.29.110.7:443, duration:2.352000 s, error:null}  
{\"hash\":\"Fm1LTYXuHg2xpqJ0-lTcPE11zUcY\",\"key\":\"1.jpg\"}", 
    "json": true, 
    "method": "POST", 
    "networkBroken": false, 
    "oK": true, 
    "reqId": "Y40AAADoLc02HWAW", 
    "serverError": false, 
    "statusCode": 200, 
    "xlog": "X-Log", 
    "xvia": ""
}

查看上传附件

http://qnvs9yac3.hn-bkt.clouddn.com/1.jpg

前端上传

https://github.com/qiniu/js-sdk

http://jssdk-v2.demo.qiniu.io/

需求梳理

初步方案

file

具体场景设计

上传资源

下载资源