天天看點

微服務之分布式檔案系統

背景

傳統Web應用中所有的功能部署在一起,圖檔、檔案也在一台伺服器;應用微服務架構後,服務之間的圖檔共享通過FTP+Nginx靜态資源的方式進行通路,檔案共享通過nfs磁盤挂載的方式進行通路,無論是單體架構還是微服務架構下的應用都存在大量圖檔、檔案讀寫操作,但是昂貴的磁盤空間、高性能伺服器無疑增加了營運成本。

是以我們希望檔案服務也能微服務、獨立化,這樣既能降低營運成本,又能對檔案進行統一的管理和維護,是以搭建獨立的檔案服務是解決檔案共享、釋放業務系統壓力的最優選擇。于是便誕生了随行付分布式檔案系統簡稱OSS(Object Storage Service),提供的海量、安全、低成本、高可靠的雲存儲服務。它具有與平台無關的RESTful API接口,能夠提供資料可靠性和服務可用性。

檔案服務的意義

随着網際網路圖檔、視訊時代的到來,對檔案的處理成為各個業務系統面臨的巨大挑戰,沒有檔案伺服器之前,系統之間處理圖檔的方式大相徑庭:FTP、NFS、資料庫存儲等等,雖然都實作了對檔案的存儲、通路,但是系統之間很難達到檔案共享,是以檔案服務可以形成一個統一的通路标準,降低各個系統之間的互相依賴,提高開發效率、釋放業務系統壓力,是以檔案服務的意義如下:

降低WEB伺服器壓力

分擔業務伺服器的I0、流程負載,将耗費資源的檔案通路、讀寫操作分離到檔案伺服器,可以提高伺服器的性能和穩定性,降低WEB伺服器成本。

獨立服務易擴充

檔案服務像微服務架構獨立化,可以有針對性的進行配置提高性能;獨立域名讓圖檔管理、CDN緩存檔案更友善,随時擴充檔案伺服器數量,即不影響業務又能增加檔案伺服器并發通路。

統一通路格式

開發者無需關心存儲路徑、存儲媒體、檔案備份等,豐富的API幫助系統快速存儲、共享檔案,提高項目開發速度。

安全認證

檔案服務對資源通路可以增加認證、權限等安全措施,防止伺服器資源被盜用,有效的隔離了資料通路。

檔案服務基本概念

為便于更好的了解對象存儲OSS,需要了解對象存儲中的幾個概念。

對象/檔案(Object)

對象是OSS存儲資料的基本單元,也被稱為OSS的檔案。對象由元資訊(Object Meta),使用者資料(Data)和檔案名(Key)組成。對象由存儲空間内部唯一的Key來辨別。對象元資訊是一個鍵值對,表示了對象的一些屬性,比如最後修改時間、大小等資訊,同時使用者也可以在元資訊中存儲一些自定義的資訊。對象的生命周期是從上傳成功到被删除為止。在整個生命周期内,對象資訊不可變更。重複上傳同名的對象會覆寫之前的對象,是以,OSS 不支援修改檔案的部分内容等操作。

存儲空間(Bucket)

存儲空間是用于存儲對象(Object)的容器,所有的對象都必須隸屬于某個存儲空間。可以設定和修改存儲空間屬性用來控制地域、通路權限、生命周期等,這些屬性設定直接作用于該存儲空間内所有對象,是以可以通過靈活建立不同的存儲空間來完成不同的管理功能。

同一個存儲空間的内部是扁平的,沒有檔案系統的目錄等概念,所有的對象都直接隸屬于其對應的存儲空間。

每個使用者可以擁有多個存儲空間。

存儲空間的名稱在 OSS 範圍内必須是全局唯一的,一旦建立之後無法修改名稱。

存儲空間内部的對象數目沒有限制。

通路密鑰(AppKey & AppSecret)

AppKey代表應用身份,AppSecret即應用密鑰,用于生成簽名認證,請求檔案服務時必須要傳遞appkey和簽名生産的token,網關根據請求驗證請求的合法性性和時效性。

檔案服務的功能

應用場景 功能描述

上傳檔案 建立存儲空間後,您可以上傳任意檔案到該存儲空間

搜尋檔案 可以在存儲空間中搜尋檔案或檔案夾

檢視或下載下傳檔案 通過檔案 URL 檢視或者下載下傳檔案

删除檔案或檔案夾 删除單個或者多個檔案/檔案夾,還可以删除分片上傳産生的碎片,節省存儲空間

通路權限 可以通過應用授權和桶授權的方式,授予存儲空間和對象通路權限的通路政策

通路資訊 自動記錄對OSS資源的詳細通路資訊

防盜鍊 防止OSS上的資料被其他人盜用,設定防盜鍊

監控服務 預警OSS服務使用情況的實時資訊,如基本的系統運作狀态和性能

API和SDK OSS 提供 RESTful API和各種語言的SDK開發包友善您快速進行二次開發

架構設計

OSS以分布式檔案系統ceph作為底層存儲,支援SDK或者浏覽器以http的形式上傳和下載下傳檔案,網關負責路由通路請求到檔案服務叢集ossWork,ossWork生成檔案唯一儲存路徑後存儲檔案到ceph,并傳回加密後通路位址給使用者。 架構圖如下:

微服務之分布式檔案系統

原理介紹:

1.OSS采用OpenResty作為網關處理請求轉發和校驗,OpenResty彙聚了nginx的核心功能子產品,還支援lua腳本友善對nginx功能的擴充,而且nginx多路複用機制和非阻塞的IO非常适合耗時短、業務簡單的校驗操作:權限驗證、防盜鍊、黑白名單等,不僅如此nginx還能作為網關的緩存,這些特性極大提升了網關性能和并發通路。

2.ossWork作為檔案服務,處理圖檔水印、縮放、url加密、解密等,還封裝與底層存儲的互動。

3.ossKeeper作為檔案管理背景,負責權限接入注冊、申請、監控報表展示。

4.ossMonitor日志收集、計算彙總、資料存儲。

5.ossBackup負責檔案異步備份。

oss子系統相關流程圖如下:

微服務之分布式檔案系統

核心實作

OSS主要為随行付各個業務系統提供檔案共享和通路服務,并且可以按應用統計流量、命中率、空間等名額。下面将介紹OSS核心功能以及實作。主要包括:緩存、使用者認證、權限管理、url加密解密、監控統計等。

緩存

提升性能的關鍵是緩存,OSS采用二級緩存:浏覽器緩存、網關層緩存提升響應速度,具體如下:

微服務之分布式檔案系統

第一次請求檔案時,OSS傳回檔案給浏覽器http的狀态碼是200

第二次請求時同一個檔案時,伺服器根據請求中HTTP協定中的max-age/Expires,判斷檔案未修改,傳回狀态碼403,告訴浏覽器可以繼續使用本地緩存

第三次請求F5強制重新整理,網關根據If-Modified-Since、Cache-Control:no-cache和Pragma:no-cache等資訊重新傳回nginx中緩存檔案

第四次請求url時,requesturi不一樣但檔案是同一個,nginx根據requesturi判斷網關中無此檔案,請求底層存儲傳回檔案。

使用者認證

為避免檔案、圖檔盜用,浪費伺服器流量和IO等資源,OSS采用防盜鍊的方式認證請求。每個使用OSS服務的系統都需要進行注冊、申請應用,成功後自動生成appkey、appsecret。appkey代表應用身份,appsecret即應用密鑰,用于生成簽名認證,請求檔案服務時必須要傳遞appkey和簽名生産的token,網關根據請求驗證請求的合法性性和時效性。背景管理appkey的生成及防盜鍊的簽名如下圖:

微服務之分布式檔案系統
微服務之分布式檔案系統

手機終端認證

手機端認證同server端一樣,但是由于賬戶資訊的安全問題,appkey和appsecret隻能儲存在服務端,手機終端通路oss時無法生成簽名,那麼手機端如何通路oss服務?這裡我們采用oauth認證的原理:

微服務之分布式檔案系統

app使用者登入終端系統,App發送請求OSS request請求

server收到請求後,向OSS申請資源的臨時授權token

OSS接收授權請求後,生成臨時通路token傳回給server

server組裝檔案位址與臨時的token,傳回給app

權限管理

每個應用有了自己的appkey,檔案通路時通過appkey驗證身份,預設檔案的歸屬隻有上傳者可以檢視或修改,上傳者可以授權給其他賬戶,通過在背景管理-權限配置功能授權授權的級别分為:修改、檢視、删除,不同的級别對應不同的操作,背景管理系統會實時同步檔案權限到檔案系統。這樣其他賬戶隻需要傳遞自身的appkey就可以對此檔案通路。具體流程及具體配置如下:

微服務之分布式檔案系統
微服務之分布式檔案系統

URL加解密、規範(實作參考)

底層存儲中的檔案名稱必須全局唯一,oss采用自定義算法生成檔案名稱,命名規範=時間戳+分隔符+線程ID+分隔符+程序ID+分隔符+用戶端IP,URL規範圖解如下:

微服務之分布式檔案系統

為了保證oss伺服器的安全,防止程式檔案和目錄外洩,oss對url進行了私有協定的加密,按分隔符“_”對每一項進行base64編碼,再按62位字典碼加密生成加後的url,當然也有其他的算法實作,是要實作url加密即可。解密是對加密的逆向操作,解密後的url即為儲存的通路url。服務端的規範樣例及用戶端的url規範樣例:

微服務之分布式檔案系統
微服務之分布式檔案系統

oss統計監控

為保證檔案服務的品質和可靠性,系統的監控和告警是必不可少的,各個階段的運作資訊,以日志的形式寫到檔案中,再使用Flume日志收集元件采集各個子系統的日志,按日志類别直接發送到kafka的不同topic,ossMonitor讀取kafka中消息,以時間為機關計算流量、命中率,以空間為機關統計使用率,根據上傳日志是否有異常發送告警郵件,流程如下:

微服務之分布式檔案系統

Flume是由cloudera軟體公司産出的可分布式日志收集系統,由source,channel,sink三個元件組成:

Source:

從資料發生器接收資料,并将接收的資料以Flume的event格式傳遞給一個或者多個通道channal,Flume提供多種資料接收的方式,比如Avro,Thrift,txt等

Channel:

channal是一種短暫的存儲容器,它将從source處接收到的event格式的資料緩存起來,直到它們被sinks消費掉,它在source和sink間起着一共橋梁的作用,channal是一個完整的事務,這一點保證了資料在收發的時候的一緻性. 并且它可以和任意數量的source和sink連結. 支援的類型有: JDBC channel , File System channel , Memort channel等.

Sink:

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

統計圖如下:

微服務之分布式檔案系統