微服務之分佈式文件系統

背景

傳統Web應用中全部的功能部署在一塊兒,圖片、文件也在一臺服務器;應用微服務架構後,服務之間的圖片共享經過FTP+Nginx靜態資源的方式進行訪問,文件共享經過nfs磁盤掛載的方式進行訪問,不管是單體架構仍是微服務架構下的應用都存在大量圖片、文件讀寫操做,可是昂貴的磁盤空間、高性能服務器無疑增長了運營成本。nginx

因此咱們但願文件服務也能微服務、獨立化,這樣既能下降運營成本,又能對文件進行統一的管理和維護,因此搭建獨立的文件服務是解決文件共享、釋放業務系統壓力的最優選擇。因而便誕生了隨行付分佈式文件系統簡稱OSS(Object Storage Service),提供的海量、安全、低成本、高可靠的雲存儲服務。它具備與平臺無關的RESTful API接口,可以提供數據可靠性和服務可用性。算法

文件服務的意義

隨着互聯網圖片、視頻時代的到來,對文件的處理成爲各個業務系統面臨的巨大挑戰,沒有文件服務器以前,系統之間處理圖片的方式截然不同:FTP、NFS、數據庫存儲等等,雖然都實現了對文件的存儲、訪問,可是系統之間很難達到文件共享,因此文件服務能夠造成一個統一的訪問標準,下降各個系統之間的互相依賴,提升開發效率、釋放業務系統壓力,因此文件服務的意義以下:數據庫

下降WEB服務器壓力apache

分擔業務服務器的I0、流程負載,將耗費資源的文件訪問、讀寫操做分離到文件服務器,能夠提升服務器的性能和穩定性,下降WEB服務器成本。json

獨立服務易擴展bootstrap

文件服務像微服務架構獨立化,能夠有針對性的進行配置提升性能;獨立域名讓圖片管理、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

統計圖以下:

相關文章
相關標籤/搜索