1. 程式人生 > >公開付費的非關係資料庫:百度物件儲存BOS

公開付費的非關係資料庫:百度物件儲存BOS

      今天收到百度BCS的郵件通知:

    

     百度物件儲存BOS(Baidu Object Storage),提供穩定、安全、高效以及高擴充套件儲存服務,支援單檔案最大5TB的文字、多媒體、二進位制等任何型別的資料儲存。資料多地域跨叢集的儲存,以實現資源統一利用,降低使用難度,提高工作效率。

特性

靈活管理資料

  • 建立、檢視、刪除Bucket

    • 使用者最多可以建立100個Bucket。
    • 使用者可以修改、檢視Bucket的訪問許可權。
  • 上傳、檢視、刪除Object

    • 使用者可以儲存的Object沒有數量限制。
    • Object支援文字、多媒體、二進位制等任何型別的資料。
    • 每個Object可包含從0位元組到5TB的資料。
    • 使用者可使用通用的和自定義的元資訊機制來定義資源屬性。

大檔案分塊上傳/斷點下載

  • 對於超過5GB的超大檔案,使用者可以使用分塊上傳機制;超過5MB但不超過5GB的檔案可以由使用者選擇是否需要分塊上傳。
  • 使用者將一個超大檔案拆分成子Object(又稱Part),分別上傳這些子Object,上傳完成後BOS將自動檢查資料,並將子Object組合成一個Object,完成分塊上傳。
  • 分塊後的單個Part不能超過5GB,除最後一個Part外,單個Part不能小於5MB。
  • 該功能在網路條件較差,或上傳檔案前無法確定檔案大小等場景下具有非常好的表現。

完善的API和開發工具

  • BOS提供標準的REST介面,可與任何Internet開發工具包搭配使用。
  • BOS基於原生的REST API,主要提供了以下三類API:
    • Bucket操作
    • Object操作
    • ACL操作
  • BOS提供了多種語言的SDK,Java、Python、PHP等。

功能完善的管理平臺

  • 使用者可以通過Web管理平臺方便的操作Bucket和Object。
  • 使用者可以通過Web管理平臺中的ACCESSKEY管理功能輕鬆的建立和管理自己的Access Key ID / Secret Access Key。
  • 使用者可以通過Web管理平臺提供的監控功能,實時監控Bucket的讀寫情況和佔用空間等資訊。

海量資料儲存

  • BOS支援任何型別資料的儲存、分享及使用。允許使用者將整個儲存基礎設施轉移到雲端,利用BOS的擴充套件性和按需付費的優勢,以處理不斷增長的儲存需求。
  • BOS支援最大5TB的單檔案儲存,利用斷點上傳及下載功能,可以儲存多媒體視訊、軟體包等超大檔案。

應用場景

內容儲存和分享

BOS允許企業使用者和開發者將整個儲存基礎設施轉移到雲端,支援按需使用和付費。BOS支援任何型別資料(文字、圖片、音樂、視訊、日誌、應用程式等)的儲存,使用者既可以直接訪問,也可以把BOS作為應用程式的後端儲存,還可以將指定內容共享。

用於資料分析的儲存

無論是儲存用於分析的商業或科學資料,用於調整的圖片,還是用於轉碼的視訊,BOS都是企業使用者和開發者儲存原始資料的理想場所。BOS支援使用者使用BMR及雲媒體服務進行訪問和計算,在BMR和BOS之間的資料傳輸不會產生任何費用,降低使用者使用成本。

災備系統

BOS為災備系統提供穩定、安全、低成本和高可擴充套件的儲存支援,適用於政府和企事業單位關鍵資料的定期備份和異常恢復,有效保障核心資料的高安全性和高可用性。

網盤服務

BOS為網盤服務提供豐富的資料型別支援,滿足海量的資料儲存需求。儲存容量彈性擴充套件,儲存資料安全穩定,有力支援網盤業務需求的不斷增長,有效降低成本,提升使用者體驗。

專案實際使用驗證

直接使用JAR包

步驟如下:

1.在官方網站下載Java SDK壓縮工具包。

2.將下載的bce-java-sdk-version.zip解壓後,複製到工程資料夾中。

3.在Eclipse右鍵“工程 -> Properties -> Java Build Path -> Add JARs”。

4.新增SDK工具包lib/bce-java-sdk-version.jar和第三方依賴工具包third-party/*.jar

其中,version為版本號,經過上面幾步之後,使用者就可以在工程中使用BOS Java SDK。

執行環境

Java SDK工具包可在jdk1.6、jdk1.7、jdk8環境下執行。

版本動態

本文件針對BOS Java SDK 0.8.2版本,歷史更新如下:

版本 0.8.2

無針對BOS的更新,使用者可以繼續使用上一版本而不受影響。

版本 0.8.1

更新copyObject中對copy_source的處理方法,當source object為非標準ASCII字元(例如:中文)時使用老版本Java SDK的使用者會出現簽名無法通過的現象,請及時進行版本更新。

Java驗證程式碼

Bucket

package com.boonya.bos.bucket;

import java.util.ArrayList;
import java.util.List;
import com.baidubce.services.bos.BosClient;
import com.baidubce.services.bos.model.BucketSummary;
import com.baidubce.services.bos.model.CannedAccessControlList;
import com.baidubce.services.bos.model.Grant;
import com.baidubce.services.bos.model.Grantee;
import com.baidubce.services.bos.model.Permission;

public class Bucket
{
    /**
     * 建立bucket
     * 
     * @param client
     * @param bucketName
     */
    public void createBucket(BosClient client, String bucketName)
    {
	// 新建一個Bucket
	client.createBucket(bucketName);
    }
    
    /**
     * 獲取bucket列表
     * 
     * @param client
     */
    public void listBuckets(BosClient client)
    {
	// 獲取使用者的Bucket列表
	List<BucketSummary> buckets = client.listBuckets().getBuckets();
	
	// 遍歷Bucket
	for (BucketSummary bucket : buckets)
	{
	    System.out.println(bucket.getName());
	}
    }
    
    /**
     * 判斷Bucket是否存在
     * 
     * @param client
     * @param bucketName
     */
    public boolean doesBucketExist(BosClient client, String bucketName)
    {
	
	// 獲取Bucket的存在資訊
	boolean exists = client.doesBucketExist(bucketName);
	
	// 輸出結果
	if (exists)
	{
	    System.out.println("Bucket exists");
	} else
	{
	    System.out.println("Bucket not exists");
	}
	return exists;
    }
    
    /**
     * 刪除Bucket
     * 
     * @param client
     * @param bucketName
     */
    public void deleteBucket(BosClient client, String bucketName)
    {
	// 刪除Bucket
	client.deleteBucket(bucketName);
    }
    
    /**
     * 設定Bucket的訪問許可權
     * 
     * @param client
     * @param bucketName
     */
    public void setBucketPrivate(BosClient client, String bucketName)
    {
	client.setBucketAcl(bucketName, CannedAccessControlList.Private);
    }
    
    /**
     * 設定指定使用者對Bucket的訪問許可權
     * 
     * @param client
     */
    public void SetBucketAclFromBody(BosClient client)
    {
	List<Grant> grants = new ArrayList<Grant>(); 
	List<Grantee> grantee = new ArrayList<Grantee>();
	List<Permission> permission = new ArrayList<Permission>();
	
	// 授權給特定使用者
	grantee.add(new Grantee("UserId_1"));
	grantee.add(new Grantee("UserId_2"));
	// 授權給Everyone
	grantee.add(new Grantee("*"));
	
	// 設定許可權
	//Permission中的許可權設定包含三個值:READ、WRITE、FULL_CONTROL
	permission.add(Permission.READ);
	permission.add(Permission.WRITE);
	
	grants.add(new Grant().withGrantee(grantee).withPermission(permission));
	//client.setBucketAcl("bucketName", grants);
    }
}

Object

package com.boonya.bos.object;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import com.baidubce.services.bos.BosClient;
import com.baidubce.services.bos.model.BosObject;
import com.baidubce.services.bos.model.BosObjectSummary;
import com.baidubce.services.bos.model.CopyObjectRequest;
import com.baidubce.services.bos.model.CopyObjectResponse;
import com.baidubce.services.bos.model.GetObjectRequest;
import com.baidubce.services.bos.model.ListObjectsResponse;
import com.baidubce.services.bos.model.ObjectMetadata;
import com.baidubce.services.bos.model.PutObjectResponse;

public class Object
{
    /**
     * BOS Java SDK本質上是呼叫後臺的HTTP介面,因此BOS服務允許使用者自定義Object的Http Header
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @param content
     */
    public void setHttpHeader(BosClient client, String bucketName, String objectKey, String content)
    {
	// 初始化上傳輸入流
	ObjectMetadata meta = new ObjectMetadata();
	
	// 設定ContentLength大小
	meta.setContentLength(1000);
	
	// 設定ContentType
	meta.setContentType("application/json");
	
	client.putObject(bucketName, objectKey, content, meta);
    }
    
    /**
     * 使用者自定義元資料
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @param content
     */
    public void selfDefinitedObject(BosClient client, String bucketName, String objectKey, String content)
    {
	// 初始化上傳輸入流
	ObjectMetadata meta = new ObjectMetadata();
	
	// 設定ContentLength大小
	meta.setContentLength(1000);
	// 設定自定義元資料name的值為my-data
	meta.addUserMetadata("name", "my-data");
	
	// 上傳Object
	client.putObject(bucketName, objectKey, content, meta);
    }
    
    /**
     * 新增物件到Bucket
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @param content
     */
    public void putObject(BosClient client, String bucketName, String objectKey, String content)
    {
	// 以字串上傳Object
	PutObjectResponse putObjectResponseFromString = client.putObject(bucketName, objectKey, content);
	
	// 列印ETag
	System.out.println(putObjectResponseFromString.getETag());
    }
    
    /**
     * BOS一共支援四種形式的Object上傳,參考如下程式碼
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @param byte1
     * @param string1
     * @throws FileNotFoundException
     */
    public void PutObject(BosClient client, String bucketName, String objectKey, byte[] byte1, String string1) throws FileNotFoundException
    {
	// 獲取指定檔案
	File file = new File("/path/to/file.zip");
	// 獲取資料流
	InputStream inputStream = new FileInputStream("/path/to/test.zip");
	
	// 以檔案形式上傳Object
	PutObjectResponse putObjectFromFileResponse = client.putObject(bucketName, objectKey, file);
	// 以資料流形式上傳Object
	PutObjectResponse putObjectResponseFromInputStream = client.putObject(bucketName, objectKey, inputStream);
	// 以二進位制串上傳Object
	PutObjectResponse putObjectResponseFromByte = client.putObject(bucketName, objectKey, byte1);
	// 以字串上傳Object
	PutObjectResponse putObjectResponseFromString = client.putObject(bucketName, objectKey, string1);
	
	// 列印ETag
	System.out.println(putObjectFromFileResponse.getETag());
    }
    
    /**
     * 列出Bucket中的Object
     * 
     * @param client
     * @param bucketName
     */
    public void listObjects(BosClient client, String bucketName)
    {
	
	// 獲取指定Bucket下的所有Object資訊
	ListObjectsResponse listing = client.listObjects(bucketName);
	
	// 遍歷所有Object
	for (BosObjectSummary objectSummary : listing.getContents())
	{
	    System.out.println("ObjectKey: " + objectSummary.getKey());
	}
	
    }
    
    /**
     * 簡單的讀取Object
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @throws IOException
     */
    public void getObject(BosClient client, String bucketName, String objectKey) throws IOException
    {
	
	// 獲取Object,返回結果為BosObject物件
	BosObject object = client.getObject(bucketName, objectKey);
	
	// 獲取ObjectMeta
	ObjectMetadata meta = object.getObjectMetadata();
	
	// 獲取Object的輸入流
	InputStream objectContent = object.getObjectContent();
	
	// 處理Object
	// ...
	
	// 關閉流
	objectContent.close();
    }
    
    /**
     * 簡單的讀取Object
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @throws IOException
     */
    public void getObject2(BosClient client, String bucketName, String objectKey)
    {
	// 新建GetObjectRequest
	GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectKey);
	
	// 獲取0~100位元組範圍內的資料
	getObjectRequest.setRange(0, 100);
	
	// 獲取Object,返回結果為BosObject物件
	BosObject object = client.getObject(getObjectRequest);
	
    }
    
    /**
     * 下載Object到檔案
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     */
    public void downloadObjectToFile(BosClient client, String bucketName, String objectKey)
    {
	// 新建GetObjectRequest
	GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectKey);
	
	// 下載Object到檔案
	ObjectMetadata objectMetadata = client.getObject(getObjectRequest, new File("/path/to/file"));
    }
    
    /**
     * 只獲取ObjectMetadata
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     */
    public ObjectMetadata getObjectMetadata(BosClient client, String bucketName, String objectKey)
    {
	ObjectMetadata objectMetadata = client.getObjectMetadata(bucketName, objectKey);
	return objectMetadata;
    }
    
    /**
     * 獲取下載Object的URL
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     * @param expirationInSeconds
     * @return
     */
    public String generatePresignedUrl(BosClient client, String bucketName, String objectKey, int expirationInSeconds)
    {
	
	URL url = client.generatePresignedUrl(bucketName, objectKey, expirationInSeconds);
	return url.toString();
    }
    
    /**
     * 刪除Object
     * 
     * @param client
     * @param bucketName
     * @param objectKey
     */
    public void deleteObject(BosClient client, String bucketName, String objectKey)
    {
	
	// 刪除Object
	client.deleteObject(bucketName, objectKey);
    }
    
    /**
     * 拷貝Object
     * 
     * @param client
     * @param srcBucketName
     * @param srcKey
     * @param destBucketName
     * @param destKey
     */
    public void copyObject(BosClient client, String srcBucketName, String srcKey, String destBucketName, String destKey)
    {
	
	// 拷貝Object
	CopyObjectResponse copyObjectResponse = client.copyObject(srcBucketName, srcKey, destBucketName, destKey);
	
	// 列印結果
	System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
    }
    
    /**
     * 拷貝Object
     * 
     * @param client
     * @param srcBucketName
     * @param srcKey
     * @param destBucketName
     * @param destKey
     */
    public void copyObject2(BosClient client, String srcBucketName, String srcKey, String destBucketName, String destKey)
    {
	// 建立CopyObjectRequest物件
	CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
	
	// 設定新的Metadata
	Map<String, String> userMetadata = new HashMap<String, String>();
	
	userMetadata.put("<user-meta-key>", "<user-meta-value>");
	
	ObjectMetadata meta = getObjectMetadata(client, destBucketName, destKey);
	
	meta.setUserMetadata(userMetadata);
	
	copyObjectRequest.setNewObjectMetadata(meta);
	
	// 複製Object
	CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
	
	System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
    }
}


BosClient

package com.boonya.bos.samle;

import java.io.IOException;
import com.baidubce.auth.DefaultBceCredentials;
import com.baidubce.services.bos.BosClient;
import com.baidubce.services.bos.BosClientConfiguration;
import com.boonya.bos.bucket.Bucket;
import com.boonya.bos.object.Object;

public class Sample
{
    public static void main(String[] args)
    {
	
	/**
	 * ACCESS_KEY_ID對應控制檯中的“Access Key ID”
	 */
	String ACCESS_KEY_ID = "02b45c338869400a869aecbe3";
	
	/**
	 * SECRET_ACCESS_KEY對應控制檯中的“Access Key Secret”
	 */
	String SECRET_ACCESS_KEY = "4abf9389c29c4b36aaa9241d8";
	
	// 初始化一個BosClient
	BosClientConfiguration config = new BosClientConfiguration();
	config.setCredentials(new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY));
	
	//上面的方式使用預設域名作為BOS的服務地址,如果使用者需要自己制定域名,可以通過傳入ENDPOINT引數來指定
	/**
	 * 注意:ENDPOINT引數只能用指定的包含Region的域名來進行定義,目前BOS只提供北京一個Region,因此ENDPOINT支援主域名http://bj.bcebos.com和備域名http://bj.baidubos.com,隨著Region的增加將會開放其他可以支援的域名。
	 */
	String ENDPOINT = "http://bj.bcebos.com";
	config.setEndpoint(ENDPOINT);
	
	BosClient client = new BosClient(config);
	
	Bucket bucket=new Bucket();
	
	String bucketName="boonyabucket";
	
	if(!bucket.doesBucketExist(client, bucketName))
	{
	    bucket.createBucket(client, bucketName);
	}
	
	
	Object obj=new Object();
	
	obj.putObject(client, bucketName, "boonyakey","hello,bos!");
	
	try
	{
	    obj.getObject(client, bucketName, "boonyakey");
	} catch (IOException e)
	{
	    System.out.println("BOS獲取物件,異常:"+e.getMessage());
	}
    }
}

結果


Bucket感覺就是資料庫表(或者說是儲存區域),而Object就是資料,跟非關係資料庫的儲存方式很像,但BOS是一個開放的儲存物件平臺或者是公用資料庫儲存叢集。