项目中对象存储(OSS、COS、OBS、七牛云存储等)的实践经验
一)前言
七牛云存儲(chǔ)、阿里云OSS、騰訊云COS、華為云OBS等都是典型的對(duì)象存儲(chǔ)服務(wù),本篇文章會(huì)依次介紹一下我們?cè)谧罱鼛啄晔褂眠^程中遇到的問題,同時(shí)也介紹一下目前為止我們?cè)陧?xiàng)目中的一些實(shí)踐經(jīng)驗(yàn)(爬坑記錄),或許對(duì)你有一些幫助。
二)數(shù)年經(jīng)驗(yàn)積累
2.1 石器時(shí)代,一片混沌
由于同一個(gè)程序需要多機(jī)部署,從14年開始我們的項(xiàng)目就不再把文件保存到服務(wù)器磁盤上了,而是統(tǒng)一上傳到對(duì)象存儲(chǔ)服務(wù)中,然后把拼接后的HTTP地址保存到數(shù)據(jù)中。因?yàn)楫?dāng)時(shí)連運(yùn)維都沒有,嫌麻煩所以直接使用的是七牛云給的域名,地址類似于這樣的 "https://7xicvf.com1.z0.glb.clouddn.com/xxx.ext"。
除了域名很丑之外,很長(zhǎng)一段時(shí)間內(nèi)都沒出現(xiàn)問題,直到有一天早上我們的用戶都在群里面反饋APP中的資源無法下載,我們一看原來是七牛云給的這個(gè)域名被停止解析了(后面了解到因?yàn)閷?duì)應(yīng)的一級(jí)域名涉及到“兒童澀情”,在全球范圍內(nèi)被停止解析),當(dāng)時(shí)我們就懵了,數(shù)據(jù)庫那么多URL太多了,涉及到各種表且分散在很多字段里面,看來快速在數(shù)據(jù)庫中替換URL不現(xiàn)實(shí)了,還好我們用的是PHP框架,有一個(gè)統(tǒng)一的入口和出口,我們就在出口處進(jìn)行了string replace替換,暫時(shí)解決了這個(gè)問題。
經(jīng)過這件事情后七牛云也強(qiáng)烈建議我們綁定自己的業(yè)務(wù)域名,而且在控制臺(tái)也聲明提供的域名只供測(cè)試,做了一些措施來防止誤使用,例如會(huì)限制資源下載帶寬、瀏覽器中訪問資源地址是直接當(dāng)成附件下載而不在瀏覽器中顯示等手段。我們隨后也就綁定了業(yè)務(wù)域名,并且在數(shù)據(jù)中進(jìn)行了資源替換,但因?yàn)樯婕暗胶芏啾怼⒑芏嗔校蕴鎿Q起來很費(fèi)力氣,這也在我心里埋下了一個(gè)種子,希望有一天能夠給出一個(gè)比較完美的方案來解決遇到的這些問題。
2.2 青銅時(shí)代,暴露問題
隨著公司業(yè)務(wù)規(guī)模的擴(kuò)大,為了折扣或者進(jìn)行一些資源互換所以就得接入更多的服務(wù)商,雖然內(nèi)心是抵觸的,但還是得提供對(duì)應(yīng)的支持才行,所以我在這個(gè)時(shí)候就接入了阿里云OSS存儲(chǔ)。使用的方式還是一樣,新建一個(gè)資源桶,然后綁定公司自己的業(yè)務(wù)域名,上傳資源后就把拼接起來的URL(域名 + 路徑)放到數(shù)據(jù)庫中。
隨著團(tuán)隊(duì)的不斷擴(kuò)大,存儲(chǔ)的資源場(chǎng)景就越來越多,有私有讀的場(chǎng)景、也有公開讀的場(chǎng)景,甚至很多時(shí)候干脆會(huì)為某個(gè)業(yè)務(wù)分配一個(gè)全新的桶,讓大家愛怎么折騰就怎么折騰。如果大家的資源都放一個(gè)桶的話,當(dāng)時(shí)又做不到在程序中對(duì)路徑前綴強(qiáng)制隔離,有些操作就不方便,例如想備份某種非常重要的資源那就得把整個(gè)存儲(chǔ)桶內(nèi)容都備份才行,因?yàn)椴蝗菀讌^(qū)分哪些資源屬于哪個(gè)業(yè)務(wù)的(讓業(yè)務(wù)同學(xué)從數(shù)據(jù)庫導(dǎo)出資源更麻煩,同樣因?yàn)橘Y源會(huì)放到很多表、不同列中)。另外由于涉及到很多桶,會(huì)綁定很多個(gè)業(yè)務(wù)域名,那前端對(duì)接的時(shí)候可能就要在后端設(shè)置很多跨域的域名配置(除非是設(shè)置為*,允許所有域名的跨域請(qǐng)求,但這會(huì)出現(xiàn)安全性的問題)。
鐵器時(shí)代,初有想法
針對(duì)上面的一些場(chǎng)景,總結(jié)此時(shí)遇到的問題:
存儲(chǔ)桶綁定的業(yè)務(wù)如果發(fā)生更換。 因?yàn)閿?shù)據(jù)庫中寫入的是拼接的HTTP URL(業(yè)務(wù)域名 + 存儲(chǔ)桶中的路徑),倘若業(yè)務(wù)域名由于某些原因被替換了,那就得替換數(shù)據(jù)庫中所有的資源地址。
存儲(chǔ)桶倘若要經(jīng)常變換綁定域名。業(yè)務(wù)發(fā)展過程中會(huì)嘗試很多種CDN服務(wù)商,每次更換CDN服務(wù)商就得在數(shù)據(jù)庫中替換一次資源,雖然可以在網(wǎng)關(guān)處替換,但其實(shí)不推薦。
存儲(chǔ)桶分配得太多難以管理。項(xiàng)目越來越多、人越來越復(fù)雜,為了避免互相干涉就只能不斷分配新的桶,需要分配非常多的域名,管理起來非常累。
針對(duì)上述的問題,我們進(jìn)行嘗試通過中間件的方式來解決,因此誕生了第一個(gè)版本的存儲(chǔ)中間件,雖然后面也收到了很多吐槽,不過沒關(guān)系,有了吐槽才會(huì)有后面不斷完善的解決方案,存儲(chǔ)中間件設(shè)計(jì)詳情請(qǐng)看下文。
三)存儲(chǔ)中間件
3.1 蒸汽時(shí)代
其實(shí)中間件所有的內(nèi)容都是圍繞著我們自定義的存儲(chǔ)協(xié)議展開的,存儲(chǔ)協(xié)議的資源地址是這樣的:oss://spaceKey/fileKey.ext,分為三部分內(nèi)容:
oss,為固定的協(xié)議名稱。
spaceKey,表示存儲(chǔ)自定義存儲(chǔ)空間,一個(gè)存儲(chǔ)空間會(huì)綁定到某個(gè)服務(wù)商對(duì)象存儲(chǔ)桶的某個(gè)路徑下。
fileKey.ext 表示文件名(含擴(kuò)展名),當(dāng)然 fileKey 中也可以包含 "/",因?yàn)樵趯?duì)象存儲(chǔ)中并沒有文件夾的概念,是模擬的。
針對(duì)上面的協(xié)議,我們的中間件需要包含以下部分內(nèi)容:
管控系統(tǒng)接口,供下面的存儲(chǔ)組件SDK在內(nèi)網(wǎng)調(diào)用。允許新增存儲(chǔ)空間,并且關(guān)聯(lián)到某個(gè)服務(wù)商某個(gè)存儲(chǔ)桶的某個(gè)路徑下,還可以為某個(gè)存儲(chǔ)桶配置多個(gè)CDN域名。
存儲(chǔ)組件SDK,供業(yè)務(wù)Web應(yīng)用使用。服務(wù)端程序內(nèi)部進(jìn)行調(diào)用時(shí)都通過ossUrl(oss://spaceKey/fileKey.ext這種格式統(tǒng)稱為OssUrl,下同)進(jìn)行傳遞,只有在程序返回時(shí)才通過某種機(jī)制攔截ResponseBody并把其中的 ossUrl替換為CDN地址供用戶訪問;當(dāng)然也要提供一個(gè)靜態(tài)類把ossUrl轉(zhuǎn)成最終的CDN地址,兼容一些奇怪的場(chǎng)景需求。
3.1.1 管控系統(tǒng)設(shè)計(jì)
其中核心數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如案例如下,與我們實(shí)際業(yè)務(wù)代碼不同,這里主要是表達(dá)含義即可:
針對(duì)上面的數(shù)據(jù)結(jié)構(gòu)相關(guān)的解釋:
object_storage_space,表示存儲(chǔ)業(yè)務(wù)定義的存儲(chǔ)空間,目前有兩種訪問模式:1)公開讀私有寫2)私有讀寫,把 ossUrl 轉(zhuǎn)換成CDN地址時(shí)會(huì)用到,如果是私有讀地址則需要加上簽名信息(需要指定失效時(shí)間)。
object_storage_vendor_bucket,表示云服務(wù)商的實(shí)際存儲(chǔ)桶地址,會(huì)包含一些元數(shù)據(jù)信息,提供給存儲(chǔ)組件SDK進(jìn)行初始化嗎,例如存儲(chǔ)桶地域、Endpoint等。
object_storage_vendor_bucket_cdn,表示該服務(wù)商存儲(chǔ)桶綁定的CDN的地址,例如提供一個(gè)騰訊云的CDN域名回源到阿里云的存儲(chǔ)桶。priority表示優(yōu)先級(jí),倘若一個(gè)存儲(chǔ)桶綁定了多個(gè)CDN域名可以進(jìn)行優(yōu)先級(jí)排序,在存儲(chǔ)SDK解析CDN地址時(shí)可以用到。
object_storage_space_bucket,表示業(yè)務(wù)自定義存儲(chǔ)空間關(guān)聯(lián)到某個(gè)存儲(chǔ)服務(wù)商存儲(chǔ)桶的某個(gè)路徑下,不同空間關(guān)聯(lián)不同路徑可以防止互相干涉。
3.1.2 存儲(chǔ)組件設(shè)計(jì)
針對(duì)上面的架構(gòu)相關(guān)的解釋:
存儲(chǔ)SDK通過管控系統(tǒng)的元數(shù)據(jù)信息(配置的存儲(chǔ)空間信息)來初始化對(duì)應(yīng)云服務(wù)商的SDK執(zhí)行文件上傳。
存儲(chǔ)SDK可以通過檢測(cè)ResponseBody(我們項(xiàng)目是SpringBoot為基礎(chǔ)框架的)中的OSS URL轉(zhuǎn)換為CDN地址供用戶訪問。
四)經(jīng)驗(yàn)總結(jié)
當(dāng)然我們的業(yè)務(wù)系統(tǒng)會(huì)更加復(fù)雜一些,例如通過processor參數(shù)來適配不同云存儲(chǔ)的數(shù)據(jù)處理功能,無論使用哪家云存儲(chǔ)都可以提供一致的圖片處理方案(例如裁剪、水印、旋轉(zhuǎn)等)。而且也遇到了一些比較尷尬的坑,有各端配合上的、有知識(shí)短板導(dǎo)致方面的,這些坑不方便在這里寫下來,如有需要后面我會(huì)單獨(dú)脫敏后記錄下來。
總結(jié)
以上是生活随笔為你收集整理的项目中对象存储(OSS、COS、OBS、七牛云存储等)的实践经验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 立即学习AI:03-使用卷积神经网络进行
- 下一篇: 【面试题】你是测试工程师,如何保证软件的