傳統Web應用中全部的功能部署在一塊兒,圖片、文件也在一臺服務器;應用微服務架構後,服務之間的圖片共享經過FTP+Nginx靜態資源的方式進行訪問,文件共享經過nfs磁盤掛載的方式進行訪問,不管是單體架構仍是微服務架構下的應用都存在大量圖片、文件讀寫操做,可是昂貴的磁盤空間、高性能服務器無疑增長了運營成本。nginx
因此咱們但願文件服務也能微服務、獨立化,這樣既能下降運營成本,又能對文件進行統一的管理和維護,因此搭建獨立的文件服務是解決文件共享、釋放業務系統壓力的最優選擇。因而便誕生了隨行付分佈式文件系統簡稱OSS(Object Storage Service),提供的海量、安全、低成本、高可靠的雲存儲服務。它具備與平臺無關的RESTful API接口,可以提供數據可靠性和服務可用性。算法
隨着互聯網圖片、視頻時代的到來,對文件的處理成爲各個業務系統面臨的巨大挑戰,沒有文件服務器以前,系統之間處理圖片的方式截然不同:FTP、NFS、數據庫存儲等等,雖然都實現了對文件的存儲、訪問,可是系統之間很難達到文件共享,因此文件服務能夠造成一個統一的訪問標準,下降各個系統之間的互相依賴,提升開發效率、釋放業務系統壓力,因此文件服務的意義以下:數據庫
下降WEB服務器壓力apache
分擔業務服務器的I0、流程負載,將耗費資源的文件訪問、讀寫操做分離到文件服務器,能夠提升服務器的性能和穩定性,下降WEB服務器成本。json
獨立服務易擴展bootstrap
文件服務像微服務架構獨立化,能夠有針對性的進行配置提升性能;獨立域名讓圖片管理、CDN緩存文件更方便,隨時擴展文件服務器數量,即不影響業務又能增長文件服務器併發訪問。瀏覽器
統一訪問格式緩存
開發者無需關心存儲路徑、存儲介質、文件備份等,豐富的API幫助系統快速存儲、共享文件,提升項目開發速度。安全
安全認證bash
文件服務對資源訪問能夠增長認證、權限等安全措施,防止服務器資源被盜用,有效的隔離了數據訪問。
爲便於更好的理解對象存儲OSS,須要瞭解對象存儲中的幾個概念。
對象/文件(Object) 對象是OSS存儲數據的基本單元,也被稱爲OSS的文件。對象由元信息(Object Meta),用戶數據(Data)和文件名(Key)組成。對象由存儲空間內部惟一的Key來標識。對象元信息是一個鍵值對,表示了對象的一些屬性,好比最後修改時間、大小等信息,同時用戶也能夠在元信息中存儲一些自定義的信息。對象的生命週期是從上傳成功到被刪除爲止。在整個生命週期內,對象信息不可變動。重複上傳同名的對象會覆蓋以前的對象,所以,OSS 不支持修改文件的部份內容等操做。
存儲空間(Bucket) 存儲空間是用於存儲對象(Object)的容器,全部的對象都必須隸屬於某個存儲空間。能夠設置和修改存儲空間屬性用來控制地域、訪問權限、生命週期等,這些屬性設置直接做用於該存儲空間內全部對象,所以能夠經過靈活建立不一樣的存儲空間來完成不一樣的管理功能。
訪問密鑰(AppKey & AppSecret) AppKey表明應用身份,AppSecret即應用密鑰,用於生成簽名認證,請求文件服務時必需要傳遞appkey和簽名生產的token,網關根據請求驗證請求的合法性性和時效性。
應用場景 | 功能描述 |
---|---|
上傳文件 | 建立存儲空間後,您能夠上傳任意文件到該存儲空間 |
搜索文件 | 能夠在存儲空間中搜索文件或文件夾 |
查看或下載文件 | 經過文件 URL 查看或者下載文件 |
刪除文件或文件夾 | 刪除單個或者多個文件/文件夾,還能夠刪除分片上傳產生的碎片,節省存儲空間 |
訪問權限 | 能夠經過應用受權和桶受權的方式,授予存儲空間和對象訪問權限的訪問策略 |
訪問信息 | 自動記錄對OSS資源的詳細訪問信息 |
防盜鏈 | 防止OSS上的數據被其餘人盜用,設置防盜鏈 |
監控服務 | 預警OSS服務使用狀況的實時信息,如基本的系統運行狀態和性能 |
API和SDK | OSS 提供 RESTful API和各類語言的SDK開發包方便您快速進行二次開發 |
OSS以分佈式文件系統ceph做爲底層存儲,支持SDK或者瀏覽器以http的形式上傳和下載文件,網關負責路由訪問請求到文件服務集羣ossWork,ossWork生成文件惟一保存路徑後存儲文件到ceph,並返回加密後訪問地址給用戶。 架構圖以下:
oss子系統相關流程圖以下:
OSS主要爲隨行付各個業務系統提供文件共享和訪問服務,而且能夠按應用統計流量、命中率、空間等指標。下面將介紹OSS核心功能以及實現。主要包括:緩存、用戶認證、權限管理、url加密解密、監控統計等。
提高性能的關鍵是緩存,OSS採用二級緩存:瀏覽器緩存、網關層緩存提高響應速度,具體以下:
爲避免文件、圖片盜用,浪費服務器流量和IO等資源,OSS採用防盜鏈的方式認證請求。每一個使用OSS服務的系統都須要進行註冊、申請應用,成功後自動生成appkey、appsecret。appkey表明應用身份,appsecret即應用密鑰,用於生成簽名認證,請求文件服務時必需要傳遞appkey和簽名生產的token,網關根據請求驗證請求的合法性性和時效性。後臺管理appkey的生成及防盜鏈的簽名以下圖:
手機端認證同server端同樣,可是因爲帳戶信息的安全問題,appkey和appsecret只能保存在服務端,手機終端訪問oss時沒法生成簽名,那麼手機端如何訪問oss服務?這裏咱們採用oauth認證的原理
每一個應用有了本身的appkey,文件訪問時經過appkey驗證身份,默認文件的歸屬只有上傳者能夠查看或修改,上傳者能夠受權給其餘帳戶,經過在後臺管理-權限配置功能受權受權的級別分爲:修改、查看、刪除,不一樣的級別對應不一樣的操做,後臺管理系統會實時同步文件權限到文件系統。這樣其餘帳戶只須要傳遞自身的appkey就能夠對此文件訪問。具體流程及具體配置以下:
底層存儲中的文件名稱必須全局惟一,oss採用自定義算法生成文件名稱,命名規範=時間戳+分隔符+線程ID+分隔符+進程ID+分隔符+客戶端IP,URL規範圖解以下:
爲了保證oss服務器的安全,防止程序文件和目錄外泄,oss對url進行了私有協議的加密,按分隔符「_」對每一項進行base64編碼,再按62位字典碼加密生成加後的url,固然也有其餘的算法實現,是要實現url加密便可。解密是對加密的逆向操做,解密後的url即爲儲存的訪問url。服務端的規範樣例及客戶端的url規範樣例:
爲保證文件服務的質量和可靠性,系統的監控和告警是必不可少的,各個階段的運行信息,以日誌的形式寫到文件中,再使用Flume日誌收集組件採集各個子系統的日誌,按日誌類別直接發送到kafka的不一樣topic,ossMonitor讀取kafka中消息,以時間爲單位計算流量、命中率,以空間爲單位統計使用率,根據上傳日誌是否有異常發送告警郵件,流程以下:
Flume是由cloudera軟件公司產出的可分佈式日誌收集系統,由source,channel,sink三個組件組成:
從數據發生器接收數據,並將接收的數據以Flume的event格式傳遞給一個或者多個通道channal,Flume提供多種數據接收的方式,好比Avro,Thrift,txt等
channal是一種短暫的存儲容器,它將從source處接收到的event格式的數據緩存起來,直到它們被sinks消費掉,它在source和sink間起着一共橋樑的做用,channal是一個完整的事務,這一點保證了數據在收發的時候的一致性. 而且它能夠和任意數量的source和sink連接. 支持的類型有: JDBC channel , File System channel , Memort channel等.
sink將數據存儲到集中存儲器好比Hbase和kafka,它從channals消費數據(events)並將其傳遞給目標地.
Flume配置以下:
gateway.sources = fileEvent
gateway.channels = kafkaChannel
gateway.sinks = loggerSink
# For each one of the sources, the type is defined
gateway.sources.fileEvent.type = TAILDIR
gateway.sources.fileEvent.positionFile = / xxx.json
gateway.sources.fileEvent.filegroups = events
gateway.sources.fileEvent.filegroups.events=/xxx.log
#gateway.sources.fileEvent.type = spooldir
# The channel can be defined as follows.
gateway.sources.fileEvent.channels = kafkaChannel
#gateway.sources.fileEvent.channels = kafkaChannel
#gateway.sources.fileEvent.spoolDir = /home/app/oss_events
# Each sink's type must be defined
gateway.sinks.loggerSink.type = org.apache.flume.sink.kafka.KafkaSink
#Specify the channel the sink should use
gateway.sinks.loggerSink.channel = kafkaChannel
gateway.sinks.loggerSink.kafka.bootstrap.servers=xxx.xxx.xxx.xxx:9092
gateway.sinks.loggerSink.kafka.topic=oss-gateway-events
gateway.sinks.loggerSink.kafka.batchSize=20
gateway.sinks.loggerSink.kafka.producer.requiredAcks=1
# Each channel's type is defined.
gateway.channels.kafkaChannel.type = memory
# Other config values specific to each type of channel(sink or source)
# can be defined as well
# In this case, it specifies the capacity of the memory channel
gateway.channels.kafkaChannel.capacity = 30000
gateway.channels.kafkaChannel.transactionCapacity = 100
複製代碼
統計圖以下:
劉利鵬,隨行付架構部中間件組高級開發工程師,參與隨行付OSS設計與開發,並推廣落地。