作者:金兆旭 上海創米數聯智能科技發展股份有限公司雲服務開發及 SRE 工程師 負責公司雲端基礎設施建構及消息網關等研發工作;十眠
創米數聯是小米生态鍊首批億元俱樂部成員,主營業務為智能家居産品的研發、設計、生産和銷售,緻力于成為以居家安全為核心的産品和服務提供商,提供多品類的全屋智能家居産品及服務。公司以居家安全為核心,洞察使用者在居住環境下的智能化需求,建立實體安全、環境安全、系統安全三類場景及服務體系,主要産品包括智能錄影機、智慧門、智能貓眼、智能門鈴、智能插座等。公司旨在實作“看得見的全屋智能”,以智能家庭安全為切入點,提供多品類覆寫的智能家居解決方案。截至 2021 年 12 月 31 日,創米數聯已經在全世界 150 多個國家,銷售了超過 5500 萬台裝置,擁有了 1600 萬裝置和 500 萬裝置使用者日活。
作為小米生态鍊的一員,創米采用微服務架構支撐其千萬日活的 IOT 裝置。随着智能家居市場的快速疊代,創米面臨着釋出和疊代的穩定性挑戰,同時需要解決多方 IOT 接入面臨的性能和安全挑戰。本文将為您一一道來創米是如何應對這些挑戰的。
雲計算時代的蹒跚學步
創米雲服務從 2016 年創始之初就選擇了雲計算+微服務的技術路線,以應對面臨的大量線上使用者和裝置帶來的流量挑戰。建構微服務之初,市面上可選用的解決方案并不多,我們自主實作了一些微服務元件,如 frontend 業務網關和配置中心,并在小米生态雲上部署容器服務來處理裝置消息、裝置插件 API 和微信公衆号等相關業務,并利用 HPA 及 CronHPA 等容器彈性伸縮政策來應對動态的海量線上流量。
自此創米數聯在雲計算時代踏上了探索服務容器化的第一步。
新業務及新挑戰
從 2019 年伊始,創米數聯提出了研發自有 APP 和适配自有 APP 的智能家居裝置的發展戰略。雲服務部将研發重心轉向自有 APP 雲端業務,并逐漸接入自有品牌裝置。為了實作全球業務,創米雲服務部将相關服務部署在阿裡雲的 4 個 Region 的 ACK Pro 專有版 Kubernetes 叢集上。阿裡雲 ACK 為創米雲提供了可靠穩定的基礎設施,向下封裝好的數十款雲産品,降低了雲端運維人員的運維壓力,快速對接其他雲産品的能力也對開發人員十分友好,能夠讓創米雲服務在極短的時間内搭建一套線上可用的環境。
在自有業務研發開始階段,我們選擇了 Spring Cloud、Eureka 和 Apollo 等技術棧來搭建我們的微服務基礎架構。然而,經過一年半的摸索,我們發現目前的混合架構存在着不穩定、上線部署風險大以及高人力維護成本等問題。
是以,從 2021 年開始,創米雲服務決定改變現有的微服務架構,逐漸擁抱雲原生。我們的目标是在滿足穩定性和低維護成本等需求的基礎上,實作所有元件的可觀測性、全鍊路的流量治理以及更加便捷高效的 DevOps 流程。
雲原生體系探索
首先我們将目前的 Spring Cloud 體系全面轉向 Spring Cloud Alibaba,使用 Nacos 替換 Eureka,以解決 Eureka 服務端壓力過大的問題,并滿足單注冊中心多環境分組的需求。由于 Apollo 在某些情況下存在容器磁盤壓力大的問題,我們逐漸将配置中心從 Apollo 替換為 Nacos。針對之前定制化的 Apollo 配置同步和本地特殊配置緩存,同樣我們也對 Nacos 用戶端進行了部分定制化改造。
初版上線時,考慮到注冊中心和配置中心的高可用性、熱更新、成本、可觀測配套等因素,我們沒有選擇自建有狀态的開源 Nacos 服務,而是直接使用了阿裡雲 MSE Nacos 專業版服務。至今,該服務一直穩定運作,沒有出現可用性問題。
全鍊路流量治理
針對全鍊路的流量治理,由于創米雲服務所處的 AIoT 行業不同于傳統網際網路行業,我們在南北向流量時不僅需要治理下遊使用者手機端 APP 及 Web 端的 HTTP 請求,還需要處理來自裝置端的 MQTT、第三方 AMQP 和 HTTP 2 長連接配接 Push 消息的流量治理。這些消息通常經由統一的上遊消息網關(消息總線)監聽,經過多級過濾器,如消息來源、消息限流和産品或特定裝置級别的白名單等,對消息進行分類和打标簽,然後對消息 Topic 正則路由并進行 HTTP 異步或 rpc 請求。隻有經過這些請求後,我們才能對其進行流量治理。
是以,創米雲服務的流量治理整體較為複雜。我們曾考慮過采用侵入式代碼和自定義負載均衡器,并開發控制台來實作高度自定義的流量方案。我們還考慮過使用 Istio Service Mesh 的方案治理流量。然而,前者在目前百萬級别裝置消息的情況下性能嚴重受限,後者由于裝置消息鍊路較長、打标較多,導緻實作全鍊路灰階時配置檔案實作較為複雜,而且 Envoy 代理無法完整攔截消息總線請求等問題,是以我們否定了這兩種方案。之後在選型過程中,我們采用了 MSE 微服務治理。
我們傳統的 API 業務流量治理選用了多域名、多租戶環境、節點隔離加多業務網關的方案配合 MSE 微服務治理來實作多個環境服務的測試開發及線上灰階部署。我們使用多域名加 DNS 流量劃分的方式對服務重構後的業務網關新路由進行測試,保證服務重構後的安全上線。我們利用多個 K8s 叢集、K8s namespace 以及多個 namespace 的注冊配置中心的隔離建構了不同的線上環境,分别用來線上開發、線上測試、灰階以及基線環境部署。對于同一叢集不同 namespace 的應用 pod 使用多叢集隔離、應用節點親和性、反親和性以及節點污點等叢集排程手段保證環境的安全性,避免不同環境間出現的資源異常導緻基線環境不可用的情況。基線環境和灰階環境同屬不同命名空間的相同節點池内,測試和開發環境應用 pod 部署在不同的 K8s 叢集或節點池中。我們的整體流程通常是在 feature 及 bug 修複後涉及的服務在開發環境聯調完畢,在每次測試流程前将 feature 服務部署至測試環境,通過藍綠測試将測試人員的流量導向測試環境,在多輪的覆寫及回歸測試完成後,将服務部署至灰階環境,再将測試人員及 Beta 測試使用者的流量導向灰階環境,經過一定時間的檢驗後,逐漸将線上基線流量導向灰階環境,灰階環境流量完成 100% 灰階後,替換基線環境鏡像,最後逐漸将灰階流量倒流至基線環境。
在核心業務接入 MSE 微服務治理之後,創米雲服務對部分多雲部署及老項目通過 DNS 流量切分+全鍊路灰階的方式進行灰階,逐漸将自有 APP 及自有裝置的所有業務重構遷移至新項目中并全部接入 MSE 微服務,實作了雲上 API 業務的 100% 安全釋出。
在裝置消息業務的流量治理的推進過程中,為了解決無法攔截消息請求的問題,我們首先将消息總線拆分為控制器和路由器兩部分。控制器監聽各個通道的消息後僅對消息進行打标簽和分類,然後通過異步 HTTP 請求經由統一的路由器轉發到各個服務中。我們将路由器服務定義為流量治理的入口,進而解決了消息無法治理的問題。然後,我們使用統一的全鍊路灰階對打标簽後的 HTTP 請求進行藍綠和灰階的流量治理,并将其分發到指定的命名空間的指定服務中進行消息處理。
MSE 微服務治理接入非常簡單,隻需要在 Helm 或元件中心安裝 ack-onepilot 元件,重新開機服務便可自動注入服務,除此之外 MSE 提供了較為友好的全鍊路灰階配置界面,較 Istio 方案更加易于配置和上手。通過這樣的流程,創米雲服務成功實作了裝置服務的更新、雲雲裝置的對接以及固件 OTA 版本的疊代過程中的安全釋出。
無損上下線解決釋出擴縮容流量損失問題
在之前的服務發版部署或 pod 彈性伸縮過程中經常會有部分請求出現逾時或不可用的情況,由于創米雲服務承載了大量的使用者裝置請求,這些流量損失輕則導緻裝置消息重試,嚴重時會影響部分使用者裝置的可用性,後續我們了解了 MSE 微服務治理提供了無損上下線及服務預熱功能,決定将相關服務全部接入了 MSE 微服務治理的無損上下線,并調整對應服務的就緒檢查,在後續的服務上下線過程中經觀察再未出現因為流量損失導緻的請求不可用的情況,一定程度上避免了由部署釋出和服務縮容引起的線上流量損失問題。
可觀測體系
為了實作可觀測性,我們早期就将阿裡雲 SLS 日志服務內建到自有業務架構中。然而,我們遇到了業務索引不規範、唯一 RequestId 索引異步丢失以及 Spring Cloud Gateway 等 Reactive 架構應用日志異步寫入 Location 導緻 CPU 占用過高等問題。是以,我們對目前的日志規範進行了改進,并在多個鍊路追蹤方案中選擇了 Skywalking。我們将 Skywalking 的 TraceId 寫入 SLS 日志索引中,并通過對 ThreadLocal 的改造實作了異步線程的日志索引資訊傳遞。我們的服務挂載了 Skywalking Agent,并自定義了可選插件,然後接入了阿裡雲鍊路追蹤服務。相比自建 ElasticSearch 叢集,阿裡雲鍊路追蹤服務更經濟實惠且免維護,鍊路追蹤服務可以直接将項目關聯到指定的 SLS logstore 中,更友善進行鍊路問題排查。在上線的第一個月裡,鍊路追蹤服務幫助我們解決了多個項目中的接口性能問題。
創米雲服務的名額資訊的觀測主要依賴于 ARMS ACK、ARMS ACK Pro、ARMS 雲服務等多個開箱可用的 Grafana Dashboard,它們提供了相當完善的叢集、Node、Pod 等多個次元的名額資訊,除此之外我們依然會使用阿裡雲雲監控或自定義一些 Grafana Dashboard 用來關注其他部分名額。創米雲服務為了快速預警,設定了雲産品、SLS 日志、K8s 事件等多個次元的告警配置,對報警進行降噪調優,根據告警等級設定了電話、短信、郵件和飛書群多個通道的報警通知,建立了相當全面的服務告警體系,以便相關人員及時發現問題,避免線上損失。
CI/CD 提效
早些時候由于多雲部署的問題,我們并沒有統一的全自動 CI/CD 解決方案,為了解決雲端 DevOps 建構部署和上線安全性等問題,我們将所有的 Devops 流程開始全面轉向阿裡雲雲效。首先,我們将雲服務代碼從自建的 Gitlab 完全同步到阿裡雲 CodeUp 代碼庫中,并将之前的 Gitlab CI/CD 和 Jenkins 的 CI/CD 方案全部遷移到阿裡雲雲效流水線。我們建立了單 Region、多 Region、多雲項目的多條流水線,實作了從代碼送出、手動或自動觸發建構,到自動部署到指定的 K8s 叢集和命名空間的全流程。每次建構和部署完成後,我們會發送飛書通知并調用 Newman 自動化測試腳本的 WebHook,根據自動化測試結果報告,評估每次服務版本釋出是否滿足安全規範。
穩定性評估與演練
對于線上環境穩定性評估,創米雲服務選用了混沌工程的方式來檢驗服務的可用性,創米雲服務根據自身業務對 Java 應用 OOM、緩存擊穿、網絡延遲、K8s Pod 資源、K8s 系統元件、關鍵雲服務等多個次元對自身環境的服務進行全方位的演練排查,并檢驗可觀測性中告警配置的靈敏度。我們在沒有造成線上損失的情況下發現并修複了部分漏洞、完善了多 AZ 的雲服務資源的建設、調整了未觸發告警的配置,使自身架構更加健壯。在一定程度上幫助創米雲服務在及時彌補了在 HA 方面不足,并在後續的架構設計中提出了高可用優先的原則。
未來展望
未來創米雲服務将業務網關逐漸轉型為雲原生網關+WASM 插件方案,代替繁重的 Spring Cloud Gateway 業務網關,進一步提升網關性能、靈活性和可擴充性,并接入現有可觀測體系。我們将繼續緻力于創新和技術更新,為使用者提供更優質的産品體驗。