五年雙十一:SLS數據管道發展之路

日誌服務SLS是一款飛天團隊自研產品,服務雲上雲下3W+客戶,並在阿里經濟體中做爲日誌數據的基礎設施,在過去幾年中經歷屢次雙11、雙12、新春紅包錘鍊。前端

在2019雙十一中:算法

  • 服務阿里經濟體3W+ 應用,1.5W外部獨立客戶
  • 峯值30TB/min、單集羣峯值11TB/min
  • 單日誌峯值600GB/min
  • 單業務線峯值1.2TB/min
  • 支持核心電商、媽媽、螞蟻、菜鳥、盒馬、優酷、高德、大文娛、中間件、天貓精靈等團隊日誌的全量上雲
  • 與30+數據源、20+數據處理、計算系統無縫打通(以下)

可以服務這個體量和用戶規模,對產品的功能、體驗、系統的穩定性和可靠性的要求是很高的。感謝阿里經濟體獨一無二的環境與挑戰,使得咱們過去五年中持續不斷地對產品與技術進行考驗與磨鍊。數據庫

數據管道是企業的基礎設施

數據管道是什麼?

數據管道概念誕生在2009年,提出的是LinkedIn工程師Jay Krep,Jay也是Apache Kafka做者+Confluent公司CEO。2012年他在文章《The Log: What every software engineer should know about real-time data's unifying abstraction》中提到設計管道設施的兩個初衷:後端

  • 解耦生產者與消費者,下降系統對接複雜性
  • 定義出統一格式與操做語義

這兩個核心痛點的解決+實時系統的興起使得Kafka類產品在幾年間有了一個量的飛躍,成了膾炙人口的基礎軟件。隨着數據分析系統成爲企業標配,各大廠商也逐步將數據管道產品化成服務互聯網的服務,比較有表明性的有:緩存

  • AWS:Kinesis
  • Azure:EventHub
  • IBM:BlueMix Event Pipeline

數據管道(Data Pipeline)是實現系統之間數據遷移的載體,所以包括數據的採集、傳輸鏈路、存儲隊列、消費/轉儲等都屬於數據管道的範疇。在SLS這裏,咱們專爲數據管道相關的功能集合起了一個單獨的名稱:LogHub,LogHub提供數30+種數據接入方式、提供實時數據管道、對接各種下游系統等功能。
然而數據管道因足夠底層,在企業數字化過程當中擔任重要的業務,必須足夠可靠、足夠穩定、確保數據的通暢,而且可以彈性知足流量變化需求。咱們把過去5年來咱們遇到的挑戰展開,和你們回顧下。網絡

數據管道的挑戰

管道這個概念很是簡單,以致於每一個開發者都能用20行代碼寫一個原型出來:架構

  • Immutable隊列,只支持寫入,不支持更改
  • 消費者寫入後返回,寫入時保序
  • 消費者能夠根據點位來消費數據
  • 數據沒法更改,只能根據TTL(寫入前後順序)進行刪除

但在現實過程當中,維護一個天天讀寫百億次,幾十PB數據流量,而且被萬級用戶依賴的管道是一件頗有挑戰的事情,舉幾個例子:併發

  • 生產者:某個消費者程序寫錯了,忽然引發一大波流量把管道入口都佔滿了。某些數據源因促銷活動,流量在一個小時內上漲至原先十幾倍或幾百倍
  • 消費者:對一個數據源,同時有20+訂閱者來同時消費數據
  • 天天有幾百個數據源接入,方式各不相同,須要大量適配

這樣例子天天都在發生,如何把簡單的管道作得不簡單,須要大量的工做,在下面篇幅中咱們娓娓道來。負載均衡

挑戰1:生產者適配

SLS 初版本支持一類數據源-- 飛天格式的日誌文件,在五年中逐步擴展到各語言SDK,移動端,嵌入式芯片,物聯網和雲原生等環境:less

飛天日誌

SLS起源與阿里雲的飛天項目,當時咱們飛天有一個基礎的日誌模塊,幾乎全部的系統都會使用這個模塊打印日誌,因此最開始咱們開發了Logtail用於採集飛天日誌,當時的Logtail還只是一個阿里雲飛天系統內部使用的工具。

SDK可擴展

隨着非阿里雲團隊使用,因此咱們擴展了Logtail,支持通用的日誌格式,好比正則、Json、分隔符等等。同時還有不少應用不但願落盤,所以咱們提供了各類語言的SDK用於日誌上傳的代碼集成。

多平臺接入

隨着移動互聯網興起,咱們專門針對移動端開發了Android、IOS的SDK,便於用戶快速接入日誌;這個時間點阿里也開始了微服務改造、pouch開始上線,Logtail開始兼容pouch,同時咱們還專門爲Java微服務提供Log4J、LogBack的Appender,提供數據直傳的服務。
對ARM平臺、嵌入式系統、國產化系統也定製適配客戶端進行接入。

Logtail平臺化

在2018年初,爲了應對多樣化的需求,咱們爲Logtail增長了插件功能,有自定義需求的用戶能夠經過開發插件的方式擴展Logtail,實現各類豐富的功能;同時咱們也緊跟時代步伐,支持雲原生、智能設備、IoT等新興領域的數據採集

雲原生支持

隨着雲原生落地,Logtail的數據採集在18年初就開始全面支持Kubernetes,並提供了CRD(CustomResourceDefinition)用於日誌和Kubernetes系統的集成,目前這套方案已經應用在了集團內、公有云幾千個集羣中。

雲原生後的無盤化

在阿里高度虛擬化的場景中,一臺物理機可能運行上百個容器,傳統的日誌落盤採集方式對物理機磁盤的競爭很大,會影響日誌寫入性能,間接影響應用的RT;同時天天物理機須要爲各個容器準備日誌的磁盤空間,形成巨大的資源冗餘。

所以咱們和螞蟻系統部合做開展了日誌無盤化項目,基於用戶態文件系統,爲應用虛擬出一個日誌盤,而日誌盤的背後直接經過用戶態文件系統對接Logtail並直傳到SLS,以最快的方式實現日誌可看、可查。

挑戰2:多協議支持

SLS服務端支持HTTP協議寫入,也提供了衆多SDK和Agent,但在不少場景下仍是和數據源間有巨大鴻溝,例如:

  • 客戶基於開源自建系統,不接受二次改造,但願只修改一下配置文件就能接入;
  • 不少設備(交換機、路由器)提供的固定協議,沒法使用HTTP協議;
  • 各類軟件的監控信息、二進制格式等,而這些開源Agent能夠支持。

爲此SLS開展了通用協議適配計劃,除HTTP外還兼容Syslog,Kafka、Promethous和JDBC四種協議來兼容開源生態。用戶現有系統只須要修改寫入源便可實現快速接入;已有的路由器、交換機等能夠直接配置寫入,無需代理轉發;支持衆多開源採集組件,例如Logstash、Fluentd、Telegraf等。

挑戰3:客戶端(Agent)流控

在2017年先後,咱們遇到了另一個挑戰:單機Agent的多租戶流控,舉一個例子:

  • 某主機上有20+種日誌,其中有須要對帳的操做日誌,也有級別爲Info的程序輸出日誌
  • 因日誌生產者的不可控,在一段時間內可能會大量產生程序輸出日誌
  • 該數據源會在短期將採集Agent打爆,引發關鍵數據沒法採集、或延遲採集

咱們對Agent(Logtail)進行了一系列多租戶隔離優化:

  • 經過時間片採集調度保證各個配置數據入口的隔離性和公平性
  • 設計多級高低水位反饋隊列保證在極低的資源佔用下依然能夠保證各處理流程間以及多個配置間的隔離性和公平性,
  • 採用事件處理不阻塞的機制保證即便在配置阻塞/停採期間發生文件輪轉依然具備較高的可靠性
  • 經過各個配置不一樣的流控/停採策略以及配置動態更新保證數據採集具有較高的可控性

該功能上線後,通過不斷調優,較好解決了單機上多個數據源(租戶)公平分配的問題。

挑戰4:服務端流控

除了客戶端流控外,咱們在服務端也支持兩種不一樣的流控方式(Project級、Shard級反壓),防止單實例異常在接入層、或後端服務層影響其餘租戶。咱們專門開發QuotaServer模塊,提供了Project全局流控和Shard級流控兩層流控機制,在百萬級的規模下也能實現秒級的流控同步,保證租戶之間的隔離性以及防止流量穿透致使集羣不可用。

粗粒度流控:Project級

  • 每秒上千個Nginx前端,將各類接收到的Project的流量、請求次數進行彙總,發送至QuotaServer(也是分佈式架構,按照Project的進行分區)
  • Quota Server彙總全部來自各Nginx的Project統計信息,計算出每一個Project的流量、qps是否超過設置的quota上限,肯定否須要禁用Project的各種操做,以及禁用時間
  • 對於超過Quota的Project列表,QuotaServer能秒級通知到全部的Nginx前端
  • Nginx前端獲取禁用Project列表以後,馬上作出反應,拒絕這些Project的請求。

Project全局流控最主要的目的是限制用戶總體資源用量,在前端就拒絕掉請求,防止用戶實例的流量穿透後端把整個集羣打爆。真正作到流控更加精細、語義更加明確、可控性更強的是Shard級別流控。

細粒度流控:Shard級

  • 每一個shard明肯定義處理能力, 如5MB/sec寫入,10MB/sec的讀取
  • 在shard所在的機器資源有空閒的時候,儘可能處理(也有資源消耗上限限制)
  • 當shard隊列出現堵塞,根據shard流量是否超過quota,返回用戶是限流仍是系統錯誤(返回的Http錯誤碼是403仍是500),同時將Shard限流信息通知QuotaServer
  • QuotaServer接收到限流信息後,經過Nginx和QuotaServer之間存在Long pull通道,可瞬時將限流信息同步至全部的Nginx
  • Nginx端得到Shard的流控信息以後,對shard進行精確的流控

經過shard級別流控,好處很是明顯:

  • 每一個shard接收的流量有上限,異常流量在前端Nginx直接被拒絕,在各類狀況下,都沒法穿透至後端
  • Project的流控不做爲主要流控手段,只做爲用戶保護手段,防止代碼異常等狀況而致使的流量劇增
  • 根據錯誤碼(http code是403仍是500),用戶能夠和明確知道是被限流了,仍是後端日誌服務出現問題
  • 出現403流控錯誤後,用戶能夠直接經過分裂shard方式,來獲取更高的吞吐,用戶得到更多自主處理權(花錢買資源)

挑戰5:消費端(高併發)

解決日誌消費問題仍是須要從應用場景出發,SLS做爲實時管道,絕大部分消費場景都是實時消費,SLS針對消費場景提供了一層Cache,但Cache策略單一,隨着消費客戶端增多、數據量膨脹等問題而致使命中率愈來愈低,消費延遲愈來愈高。後來咱們從新設計了緩存模塊:

  • 全局緩存管理,對於每個Shard的消費計算消費權值,優先爲權值高的Shard提供緩存空間;
  • 更加精細化、啓發式的緩存管理,根據用戶近期時間的消費狀況來動態調整緩存大小;
  • 對於高保用戶,強制分配定量的緩存空間,確保不受其餘用戶影響。

上述優化上線後,集羣日誌平均消費延遲從5ms下降到了1ms之內,有效緩解雙十一數據消費壓力。

挑戰6:消費端(多實例與併發)

在以微服務、雲原生爲主導的大背景下,應用被切分的愈來愈細、整個鏈路也愈來愈複雜,其中產生的日誌種類和數量也愈來愈多;同時日誌的重要性也愈來愈強,同一個日誌可能會有好幾個甚至數十個業務方須要消費。

傳統的方式粗暴簡單,須要日誌的人本身去機器上採集,最終一份日誌可能被重複採集幾十遍,嚴重浪費客戶端、網絡、服務端的資源。

SLS從源頭上禁止同一文件的重複採集,日誌統一採集到SLS後,咱們爲用戶提供ConsumerGroup用於實時消費。但伴隨着日誌的細分化以及日誌應用場景的豐富化,SLS的數據消費逐漸暴露出了兩個問題:

  1. 日誌細分場景下,ConsumerGroup沒法支持同時消費多組Logstore的日誌,其中的日誌還可能跨越多個Project、隸屬於多個不一樣帳號,資源映射和權限歸屬管理愈加複雜;
  2. ConsumerGroup分配的最小單位是Shard,SLS的一個Shard在不開啓索引的狀況下能夠支撐幾十MB/s的寫入,而不少消費端單機並無能力處理幾十MB/s的數據,形成嚴重的生產、消費不對等。

View消費模式

針對日誌細分場景下的資源映射和權限歸屬管理等問題,咱們和螞蟻日誌平臺團隊合做開發了View消費模式(思路來源於數據庫中View),可以將不一樣用戶、不一樣logstore的資源虛擬成一個大的logstore,用戶只須要消費虛擬的logstore便可,虛擬logstore的實現以及維護對用戶徹底透明。該項目已經在螞蟻集羣正式上線,目前已經有數千個View消費實例在工做中。

Fanout消費模式

針對單消費者能力不足的問題,咱們對ConsumerGroup進一步加強,開發了Fanout消費模式,在Fanout模式下,一個Shard中的數據可交由多個消費者處理,將Shard與消費者解耦,完全解生產者消費者能力不匹配的問題。同時消費端無需關心Checkpoint管理、Failover等細節,Fanout消費組內部所有接管。

挑戰7:自動化運維

SLS對外SLA承諾99.9%服務可用性(實際99.95%+),剛開始的時候咱們很難達到這樣的指標,天天收到不少告警,常常夜裏被電話Call醒,疲於處理各類問題。總結下來主要的緣由有2點:

  1. 熱點問題:SLS會把Shard均勻調度到各個Worker節點,但每一個Shard實際負載不一併且隨着時間會動態變化,常常因爲一些熱點Shard存在同一臺機器而致使請求變慢甚至超出服務能力;
  2. 出現問題定位時間太長:線上問題終究不可避免,爲了實現99.9%的可靠性,咱們必須可以在最短的時間內定位問題,及時止血。雖然有不少監控和日誌,但人工去定位問題仍是要花不少時間。

自動熱點消除

針對熱點問題,咱們在系統中增長了調度角色,經過實時數據收集和統計後,自動作出調整,來消除系統中存在的熱點,主要有如下兩個手段:

  • 自動負載均衡

    • 系統實時統計各節點的負載,以及節點上每一個數據分區對於資源的消耗(CPU、MEM、NET等資源)
    • 負載信息彙報至調度器,調度器自動發現當前是否有節點處於高負載狀況
    • 對於負載太高節點,經過優化組合的方式,將高壓力數據分區,自動遷移到負載低的節點,達到資源負載均衡的目的
  • 自動分裂

    • 實時監控每一個Shard負載壓力
    • 若是發現持續超過單分片處理上限,則啓動分裂
    • 舊的分區變成Readonly,生成2個新的分區,遷移至其餘節點

實際場景下有不少狀況須要特殊考慮,例如顛簸狀況、異構機型、併發調度、遷移的負面影響等,這裏就再也不展開。

秒級流量分析(Root Cause Analysis)

目前SLS線上收集了數千種實時指標,天天的訪問日誌有上千億,出現問題時純粹手工調查難度很是大。爲此咱們專門開發了根因分析相關算法,經過頻繁集和差別集的方式,快速定位和異常最相關的數據集合。

如樣例中,將出現錯誤(status >= 500)的訪問數據集,定義爲異常集合A,在這個集合發現90%的請求,都是由ID=1002引發,因此值得懷疑,當前的錯誤和ID=1002有關,同時爲了減小誤判,再從正常的數據集合B(status <500)中,查看ID=1002的比例,發如今集合B中的該ID比例較低,因此更增強系統判斷,當前異常和這個ID=1002有很是高的相關性。

藉助此種方法大大縮短了咱們問題調查的時間,在報警時咱們會自動帶上根因分析結果,不少時候收到告警時就已經可以定位具體是哪一個用戶、哪臺機器仍是哪一個模塊引起的問題。

其餘挑戰:正在解決的問題

1. Shardless

爲了便於水平擴展咱們引入了Shard的概念(相似Kafka Partition),用戶能夠經過分裂Shard、合併Shard來實現資源的伸縮,但這些概念也會爲用戶帶來不少使用上的困擾,用戶須要去了解Shard的概念、須要去預估流量分配Shard數、有些時候由於Quota限制還須要手動分裂...

優秀的產品應該對用戶暴露儘量少的概念,將來咱們會弱化甚至去除Shard概念,對於用戶而言,SLS的數據管道只須要聲明必定的Quota,咱們就會按照對應的Quota服務,內部的分片邏輯對用戶完全透明,作到管道能力真正彈性。

2. 從At Least Once到Exactly Once

和Kafka同樣,SLS目前支持At Least Once寫入和消費方式,但不少核心場景(交易、結算、對帳、核心事件等)必需要求Exactly Once,如今不少業務只能經過在上層包裝一層去重邏輯來Work around,但實現代價以及資源消耗巨大。

立刻咱們會支持寫入和消費的Exactly Once語義,且Exactly Once語義場景下也將支持超大流量和高併發。

3. LogHub Select功能(過濾下推)

和Kafka相似,SLS支持的消費是Logstore級別的全量消費方式,若是業務只須要其中的一部分數據,也必須將這段時間的全部數據全量消費才能獲得。全部的數據都要從服務端傳輸到計算節點再進行處理,這種方式對於資源的浪費極其巨大。

所以將來咱們會支持計算下推到隊列內部,能夠直接在隊列內進行無效數據過濾,大大下降無效的網絡傳輸和上層計算代價。

雙12來襲!500元淘寶紅包、iPhone11等你拿https://www.aliyun.com/1212/2019/home?utm_content=g_1000092611


本文做者:元乙

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索