Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲春色第一页,精品一区二区久久,久久浮力影院

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          字節跳動全鏈路壓測(Rhino)的實踐

          字節跳動全鏈路壓測(Rhino)的實踐

          . 背景

          隨著公司業務的不斷擴張,用戶流量在不斷提升,研發體系的規模和復雜性也隨之增加。線上服務的穩定性也越來越重要,服務性能問題,以及容量問題也越發明顯。

          因此有必要搭建一個有效壓測系統,提供安全、高效、真實的線上全鏈路壓測服務,為線上服務保駕護航。

          關于全鏈路壓測的建設,業界已經有了非常多文章,但是涉及到具體的技術實現方面,卻很少介紹。本文想從全鏈路壓測系統,從設計到落地整個實踐過程,來詳細介紹下全鏈路壓測系統是具體是如何設計,以及如何落地的。希望能從技術落地實踐的角度,給同行業的同學一些參考和啟發。

          2. 解決方案

          2.1 業內實踐

          全鏈路壓測在業內已經有了廣泛的實踐,如阿里的 Amazon、PTS[1][2],美團的 Quake[3][4],京東的的 ForceBOT[5],高德的 TestPG[6]等等,都為我們提供豐富的實踐經驗,和大量優秀的技術方案。我們廣泛吸收了各大互聯網公司的全鏈路壓測建設經驗,并基于字節跳動業務需求,設計開發了一個全鏈路壓測系統 Rhino。

          2.1 架構圖

          Rhino 平臺作為公司級的全鏈路壓測平臺,它的目標是對全公司所有業務,提供單服務、全鏈路,安全可靠、真實、高效的壓測,來幫助業務高效便捷的完成性能測試任務,更精確評估線上服務性能&容量方面風險。

          因此在 Rhino 平臺設計之初,我們就定下以下目標:

          • 安全:所有壓測都是在線上完成的,所以理論上所有的壓測對線上用戶都是有損的。壓測平臺將從服務狀態,以及壓測數據兩方面去保證壓測的安全性。
          • 高效:較少壓測腳本編寫成本,數據構造和壓測監控成本,盡量自動化完成壓測過程的各個階段。
          • 準確:精確的壓力控制,準確的鏈路壓測監控,精確的壓測報告結果,以及性能&容量數據。
          • 高覆蓋:需要支撐公司內不同的業務線的壓測需求,如搜索,廣告,電商,教育,游戲等等。

          Rhino 是一個分布式全鏈路壓測系統,可以通過水平擴展,來實現模擬海量用戶真實的業務操作場景,對線上各種業務進行全方位的性能測試。它主要分為控制中心(Rhino Master)模塊,壓測鏈路服務模塊,監控系統模塊,壓測引擎模塊,如圖。(每一個模塊都是由多個微服務來完成的。如下圖每個實線圖都代表一個微服務或多個微服務)。

          3. 核心功能介紹

          • 搭建全鏈路壓測平臺,最核心主要有:數據構造、壓測隔離、鏈路治理、任務調度、壓測熔斷、壓測引擎、壓測監控等。下面我們將從這些方面詳細介紹下,在 Rhino 平臺中是如何設計和實現的。

          3.1 數據構造

          壓測過程中數據構造是最重要,也是最為復雜的環節。壓測數據的建模,直接影響了壓測結果的準確性。

          • 對于服務性能缺陷掃描,性能調優,以及新上線服務,推薦構造 Fake 數據,來壓測指定路徑。
          • 對于線上容量規劃,性能能力驗證,以及性能 Diff,推薦使用線上真實流量,使壓測結果更貼近真實情況。
          • 對于涉及到用戶賬號,用戶登錄態保持的情況,推薦使用壓測專屬測試賬號,避免影響線上真實用戶。

          基礎數據構造

          為了高效的構造特定的 Fake 壓測數據,Rhino 壓測平臺提供大量數據構造方式:

          • CSV 文件:按列分割數據,字段名取 CSV 文件第一行。數據讀取方式是按行遞增循環。如果一個壓測任務會拆分成多個 Job,那么數據文件也會拆分,避免 Job 之間的數據重復。
          • 自增:變量類型均為數字類型。每次發壓時+1,到最大值后從最小值循環使用。
          • 隨機:變量類型均為數字類型,每次發壓時隨機生成。
          • 常量:Constant,可自定義為任意值。

          壓測賬號

          在壓測過程中,有些壓測請求需要進行登錄,并保持會話;此外在很多壓測請求中涉及到用戶賬號信息 UserID,DeviceID 等數據。用戶賬號的構造問題,一直是壓測過程中非常棘手的問題。Rhino 平臺打通的用戶中心,設置了壓測專屬的賬號服務,完美地解決了壓測過程中的登錄態,以及測試賬號等問題。具體流程和使用界面,如下圖。

          3.2 壓測隔離

          壓測隔離中需要解決的壓測流量隔離,以及壓測數據的隔離。

          壓測流量隔離,主要是通過構建壓測環境來解決,如線下壓測環境,或泳道化/Set 化建設,將壓測流量與線上流程完全隔離。優點是壓測流量與線上流量完全隔離,不會影響到線上用戶。缺點:機器資源及維護成本高,且壓測結果需要經過一定的換算,才能得線上容量,結果準確性存在一定的問題。目前公司內壓測都是在線上集群上完成的,線上泳道化正在建設中。

          壓測數據隔離,主要是通過對壓測流量進行染色,讓線上服務能識別哪些是壓測流量,哪些是正常流量,然后對壓測流量進行特殊處理,以達到數據隔離的目的。目前 Rhino 平臺整體壓測隔離框架如圖。

          壓測標記

          壓測標記就是最常見的壓測流量染色的方式。

          • 對于 RPC 協議,會在請求的頭部中增加一個 Key:Value 的字段作為壓測標記。
          • 對于 HTTP 和其他協議,會在請求頭,自動注入一個 Stress 標記(Key-Value) 。
          • 壓測標記 Key:Value,其中 key 是固定的 Stress_Tag 值,但是每個壓測任務都有唯一的 Stress_Value 值,主要用于解決壓測數據沖突,以及性能問題定位。

          壓測標記透傳

          目前公司內各個基礎組件、存儲組件,以及 RPC 框架都已經支持了壓測標記的透傳。其原理是將壓測標記的 KV 值存入 Context 中,然后在所有下游請求中都帶上該 Context,下游服務可以根據 Context 中壓測標記完成對壓測流量的處理。在實際業務中,代碼改造也非常簡單,只需要透傳 Context 即可。

          Golang 服務: 將壓測標記寫入 Context 中。

          Python 服務:利用 threading.local()存儲線程 Context。

          Java 服務:利用 ThreadLocal 存儲線程 Context。

          壓測開關

          為了解決線上壓測安全問題,我們還引入了壓測開關組件。

          • 每個服務每個集群,都有一個壓測開關。只有打開壓測開關時,壓測流量才能流入到服務內,否則就會被底層微服務框架直接拒絕,業務層無感知。
          • 在每個 IDC 區域,都會有一個全局的壓測總開關。只有打開了這個全局壓測開關,壓測流量才被允許在這個 IDC 內流轉。
          • 當線上出現壓測問題,除了從源頭關閉壓測流量以外,關閉目標服務的壓測開關,也能立即阻斷壓測流量。

          壓測數據隔離

          線上壓測中,最復雜的問題就是壓測鏈路中涉及到寫操作,如何避免污染線上數據,并且能保證壓測請求保持和線上相同的請求路徑。業界有很多解決方案,常見的有影子表,影子庫,以及數據偏移,如圖[7]。

          Rhino 平臺針對不同存儲,有不同的解決方案:

          • MySQL、MongoDB:影子表。SDK 判斷是否是壓測流量,若是則根據配置映射至新表名。配置策略有兩種,一是讀寫影子表,二是讀線上表、寫影子表。
          • Redis:Redis Key 加上 Stress 前綴。如 Stress_Tag=Valuex,那么讀寫 Redis 的 Key=Valuex_Key。這樣可以解決多個壓測任務數據沖突的問題。壓測結束后,只需要對 Prefix=Valuex 做清除或過期操作即可。
          • MQ:對于消息隊列,Rhino 平臺有兩種策略。一是直接丟棄,然后針對消息隊列的性能,單獨進行壓測;二是在 Header 中透傳壓測標記,Consumer 根據壓測標記和業務需求,再做特殊處理。默認走丟棄策略,業務方可根據需求進行配置。
          • 其他存儲,如 ES,ClickHouse 等,都有壓測集群。壓測時,會將壓測請求打到指定的壓測集群中。

          服務壓測改造

          在壓測之前,需要對服務進行壓測驗證。對于不滿足壓測要求(即壓測數據隔離)的服務,需要進行壓測改造。

          1. 壓測驗證:對于存儲服務,在不打開壓測開關的前提下,通過壓測請求,發送讀寫操作都是會被拒絕。如果沒有拒絕,說明在操作存儲服務時,沒有帶上壓測 Context,需要進行改造。
          2. 壓測改造:壓測改造是線上全鏈路壓測推進中非常關鍵,而又非常困難的一個環節。對于已經上線的服務,壓測改造還極有可能會引入新的 BUG,所以經常推動起來比較困難。因此為了解決這些問題,Rhino 平臺有以下幾個解決方案:

          a. 盡量減少代碼改動,并給出完整的指導手冊及代碼示例,減少 RD 的工作量,降低代碼錯誤的可能性

          b. 提供簡單便捷的線上線下 HTTP&RPC 的壓測請求 Debug 工具,方便代碼改動的驗證

          c. 對于新項目,在項目開始初期,就將壓測改造加入項目開發規范中,減少后期的代碼改動

          3.3 鏈路治理

          鏈路梳理

          請求調用鏈,對于線上壓測是非常重要的:

          • 提供清晰壓測流量地圖,并提供完整的鏈路監控。
          • 完成服務依賴的梳理,檢測壓測所依賴的服務/中臺是否具備壓測的條件,是否需要壓測改造。
          • 鏈接壓測開關管理,壓測上下游周知等。

          Rhino 平臺通過公司的流式日志系統來完成調用鏈檢索的。一個服務在被請求或者請求下游時,都會透傳一個 LogID。RPC 框架會打印調用鏈日志(包括 RPC 日志-調用者日志,Access 日志-被調用者日志),所有日志中都會包含這個 LogID。通過 LogID 將一個請求所經過的所有服務日志串起來,就完成調用鏈檢索。

          Rhino 平臺在公司流式日志系統提供的鏈路梳理功能基礎上,進行了進一步優化,以滿足壓測需要:

          • 自動梳理:由于公司采用微服務架構,每個請求背后的調用鏈路及其復雜,單純靠人工維護是無法完成的。 用戶只需要提供請求中 LogID,Rhino 平臺就能快速梳理出該請求經過的服務節點,如圖。
          • 實時梳理:由于線上服務不斷在變化,上線下線新增等,因此同一個請求的調用鏈也是不斷變化的。Rhino 平臺建議一般使用 1 個小時內的 LogID 進行梳理。
          • 多調鏈路合并:同一個接口,不同參數下的調用鏈是不盡相同的。Rhino 平臺會將多個 LogID 梳理的結果自動進行合并,來補全調用鏈,保證鏈路梳理結果的準確性和完整性。

          測周知

          雖然 Rhino 平臺對于壓測有很多的安全保障措施,但是對于大型壓測,保證信息的通暢流通也是非常重要的。因此在壓測周知方面,Rhino 平臺也提供了很多解決方案:

          • 一鍵拉群:梳理完鏈路后,在壓測前可以一鍵拉群,將鏈路中上下游服務的 Owner 拉到同一個群里,同步壓測信息。
          • 壓測周知:每個壓測開始執行時,都會向壓測周知群里推送消息,如壓測 QPS,壓測時長等信息。

          • 壓測事件:在壓測開始執行時,Rhino 平臺還會向目標服務的事件隊列中發送一個壓測事件,方便快速評估/定位穩定性問題是否是壓測導致,減少 RD 線上問題排查的干擾。

          壓測開關管理

          在壓測之前,需要開啟整體鏈路的壓測開關的,否則壓測流量就會被服務拒絕,導致壓測失敗。

          • 一鍵開啟:在壓測執行之前,Rhino 平臺可以一鍵開啟鏈接上所有節點的壓測開關。
          • 壓測開關開啟周知:壓測開關開啟時,Rhino 平臺會自動給對應服務 Owner 推送相關信息,確保服務 Owner 了解相關壓測信息,上游會有壓測流量會經過其服務。
          • 靜默關閉:壓測開關到期后,Rhino 會自動靜默關閉壓測開關,以保證線上服務的安全。

          服務 Mock

          對于調用鏈中不能壓測的服務(敏感服務),或者第三方服務,為了壓測請求的完整性,就需要對這些服務進行 Mock。業界通用的 Mock 方案有:

          1. 修改業務代碼,修改服務調用為空轉代碼。優點:實現成本低。 缺點:返回值固定,代碼&業務入侵高,推動困難。如要 Mock 位置比較靠下游,超出部門覆蓋業務范圍,推動就非常麻煩。
          2. 通用 Mock 服務。通用 MockServer,會根據不同用戶配置不同 Mock 規則,執行對應的響應延時,并返回對應響應數據。優點:無代碼入侵,業務方無感知。 缺點:實現成本高。

          由于字節整個公司都采用微服務架構,導致一次壓測涉及鏈路都比較長,快速無業務入侵的 Mock

          方式成為了首選。Rhino 平臺是通過公司 Service Mesh 和 ByteMock 系統來實現了高效的,對業務透明的服務 Mock。

          壓測執行前,Rhino 平臺需要向 Service Mesh 注冊染色轉發規則,并向 Mock 服務注冊 Mock 規則。然后在壓測流量中注入 Mock 染色標記,才能完成服務 Mock:

          1. 基于 Service Mesh 的染色流量轉發。首先需要在壓測流量中注入轉發染色標記,并在 Service Mesh 中注冊對應的轉發規則。Service Mesh 檢測到染色流量后,就會將其轉發到指定的 Mock Server 上,如圖。
          2. 基于 Mock Server 的請求規則匹配。首先在 Mock Server 上注冊 Mock 規則,以及匹配的 Response 和響應時延。當 Mock Server 接收到請求后,會根據規則進行響應,如圖。

          3.4 發壓模式

          最小調度單元

          Rhino 平臺中,壓測 Agent 就是一個最小調度單元。一次壓測任務,通常會拆分成多個子 Job,然后下發到多個 Agent 上來完成。

          • 最小化容器部署,減少資源浪費。壓測對機器資源消耗是非常高的,通常 CPU &Memory 的使用率都在 80%以上。但是沒有壓測執行時間內,機器資源使用率<5%。如果長期占用大量的資源,將會對機器資源造成極大的浪費。壓測 Agent 都采用容器化部署,并且每個容器的資源規格也盡可能小,這樣既能滿足日常壓測需求,也不會占用太多的機器資源。
          • 獨占 Agent,增加壓測執行穩定性:單個容器內只啟動一個 Agent 進程,單個 Agent 同時只能被一個壓測任務占用,避免多任務多進程的干擾和資源競爭,增加壓測的穩定性。
          • 動態擴容,支撐海量 QPS 發壓:壓測高峰期,Rhino 平臺會臨時申請機器資源,快速擴容,完成海量 QPS 的支撐。壓測完成后,會立即釋放機器資源,減少資源浪費。

          2020 年春節搶紅包壓測中,Rhino 臨時擴容在 4000+個實例,支撐了單次 3kw+QPS 的壓測,但日常 Rhino 平臺只部署了 100+個實例,就能滿足日常壓測需求。

          智能壓力調節

          • 動態分配壓測 Agent:在壓測過程,經常出現壓測 Agent 的 CPU/Memory 使用率過高(>90%),導致壓力上不去,達不到目標 QPS;或者壓測延時過高,壓測結果不準確的問題。Rhino 平臺在發壓的過程中,會實時監控每個壓測 Agent 的 CPU/Memory 使用率,當超過閾值時(>90%),會動態分配額外的 Agent,以降低每個 Agent 的負載,保證壓測的穩定性。
          • 智能調節壓力:在壓測過程,通常需要不斷的調節 QPS 大小,以達到性能壓測目標。這過程非常耗費精力和時間。Rhino 平臺,可以根據壓測任務設定的性能指標,智能調節 QPS 大小,當達到壓測目標后,會自動熔斷,停止壓測。

          壓測鏈路模擬

          Rhino 平臺默認將全鏈路壓測分為公網壓測和內網壓測。公網壓測主要 IDC 網絡帶寬,延時,IDC 網關新建連接、轉發等能力;內網壓測,主要是壓測目標服務,目標集群的 性能,容量等。

          • 對于內網壓測,默認都要求同 IDC 內發壓,減少網絡延時的干擾。
          • 對于公網壓測,Rhino 平臺在公司 CDN 節點上都有部署 Agent 節點,利用了 CDN 節點剩余計算能力,完成了公網壓測能力的建設。

          同城多機房,異地多機房

          Rhino 平臺在各個 IDC 都有部署 Agent 集群。各個 IDC 內服務的壓測,默認會就近選擇壓測 Agent,來減少網絡延時對壓測結果的干擾,使得壓測結果更精準,壓測問題定位更簡單。

          邊緣計算節點 Agent

          除了多機房部署之外,Rhino 平臺還在邊緣計算節點上也部署了壓測 Agent,來模擬各種不同地域不同運營商的流量請求,確保流量來源,流量分布更貼近真實情況。在 Rhino 平臺上可以選擇不同地域不同運營商,從全國各個地區發起壓測流量。

          3.5 壓測熔斷

          為了應對線上壓測風險,Rhino 平臺提供兩種熔斷方式,來應對壓測過程中的突發事件,來降低對線上服務造成的影響。

          基于告警監控的熔斷

          每個壓測任務,都可以關聯調用鏈中任意服務的告警規則。在壓測任務執行過程,Rhino 平臺會主動監聽告警服務。 當調用鏈中有服務出現了告警,會立即停止壓測。對于沒有關聯的告警,Rhino 平臺也會記錄下來,便于壓測問題定位。

          基于 Metric 的熔斷

          自定義監控指標及閾值,到達閾值后,也會自動停止壓測。目前支持 CPU、Memory、 上游穩定性、錯誤日志,以及其他自定義指標。

          此外,除了 Rhino 平臺自身提供的熔斷機制以外,公司服務治理架構也提供了很多額外的熔斷機制,如壓測開關,一鍵切斷壓測流量;過載保護,服務過載時自動丟棄壓測流量。

          3.6 任務模型

          HTTP 任務

          對于 HTTP 協議,參考了 Postman,全部可視化操作,保證所有人都能上手操作,極大降低了壓測的使用門檻和成本。

          RPC 任務

          對于 RPC 任務,Rhino 也自動完成了對 IDL 的解析,然后轉換成 JSON 格式,便于用戶參數化處理。

          自定義-Go Plugin

          對于非 HTTP/RPC 的協議,以及有復雜邏輯的壓測任務,Rhino 平臺也提供了完善的解決方案——Go Plugin。

          Go Plugin 提供了一種方式,通過在主程序和共享庫直接定義一系列的約定或者接口,就可以動態加載其他人編譯的 Go 語言共享對象,使得主程序可以在編譯后動態加載共享庫,實現熱插拔的插件系統。此外主程序和共享庫的開發者不需要共享代碼,只要雙方的約定不變,修改共享庫后也不再需要重新編譯主程序。

          用戶只要根據規范要求,實現一段發壓業務邏輯代碼即可。Rhino 平臺可以自動拉取代碼,觸發編譯。并將編譯后的插件 SO 文件分發到多個壓測 Agent。 Agent 動態加載 SO 文件,并發運行起來,就可以達到壓測的目的。此外,Rhino 還針對常見 Go Plugin 壓測場景,建立了壓測代碼示例代碼庫。對于壓測新手,簡單修改下業務邏輯代碼,就可以完成壓測了。這樣就解決了非常見協議,以及復雜壓測場景等的壓測問題。

          3.7 壓測引擎

          單 Agent 多引擎

          壓測調度的最小單元是壓測 Agent,但是實際每個 Agent 中有掛載多種壓測引擎的,來支撐不同的壓測場景。Rhino 平臺在壓測數據和壓測引擎之間增加了一個壓測引擎適配層,實現了壓測數據與壓測引擎的解耦。壓測引擎適配層,會根據選擇不同的壓測引擎,生成不同 Schema 的壓測數據,啟用不同的引擎來完成壓測,而這些對用戶是透明的。

          壓測引擎

          在壓測引擎上,我們有開源的壓測引擎,也有自研的壓測引擎。

          開源壓測引擎的優點是維護人多,功能比較豐富,穩定且性能好,缺點就是輸入格式固定,定制難度大。此外 Agent 與開源壓測引擎之間通常是不同進程,進程通信也存在比較大的問題,不容易控制。

          自研壓測引擎,優點是和 Agent 通常運行在單進程內,比較容易控制;缺點可能就是性能稍微差一些。但是 Golang 天然支持高并發,因此自研和開源之間的性能差距并不明顯。

          • HTTP 協議:默認 Gatling ,單機發壓性能非常好,遠超于 Jmeter。對于智能壓測,或動態調節的情況,會切換到自研壓測引擎上。
          • RPC 協議:自研引擎,主要利用 Golang 協程+RPC 連接池,來完成高并發壓測。
          • GoPlugin 協議:自研引擎,利用 Golang Plugin 可動態裝載的特性,自動裝載自定義壓測插件,來完成壓測。

          3.8 壓測監控

          客戶端監控

          由于公司監控系統,最小時間粒度是 30s,30s 內的數據會聚合成一個點。這個時間粒度對于壓測來說是比較難以接受的。因此,Rhino 平臺自己搭建了一套客戶端監控系統。

          • 每個 Request 都會以請求開始時間為基準打一個點。
          • 單個 Agent 內,會將相同任務相同接口,1s 內的打點數據在本地做一次匯總,上報到 Kafka 中。
          • 監控服務會消費 Kafka 中的打點數據,將多個 Agent 上報的數據進行再次匯總,然后寫入數據庫中。
          • 前端監控報表會實時拉取數據庫中監控匯總數據,繪制實時監控曲線
          • 在監控數據匯總流程中,對于請求響應時間的 PCT99 計算,是比較難處理的:目前 Rhino 平臺采用的 T-Digest 算法來計算 1 秒內的 PCT99整個時間段內的 PCT99 的計算,則是以 PCT & AGV 的方式聚合。即單位時間內通過 T-Digest 計算 PCT99;整個時間段內的 PCT99,則是對所有點的 PCT99 取平均值。整體計算方案已與公司服務端監控算法對齊,目的是減少客戶端監控與服務端監控之間的 Gap,減少壓測結果分析的干擾因素。

          服務端監控

          服務端監控,直接接入了公司 Metric 系統。

          • 在壓測過程中,Rhino 平臺會提供整條鏈路上所有節點核心指標的監控大盤,并高亮顯示可能存在風險的節點,來提供實時預警。
          • 對于每個節點也都提供了實時的,詳細的監控曲線圖。
          • 對于每個節點默認提供 CPU、Memory、QPS 和 Error_Rate 等核心監控指標,用戶可以在 Rhino 平臺上修改監控配置,增加其他自定義監控指標。

          性能 Profile

          在壓測過程中,Rhino 平臺還可以實時采集目標服務進程的性能 Profile,并通過火焰圖的方式展示出來,方便用戶進行性能問題分析和優化,如圖。

          4. 壓測實踐

          Rhino 壓測平臺是一個面向全字節跳動公司的,為了所有研發同學提供的一站式全鏈路壓測的平臺。Rhino 平臺的研發團隊,不僅負責 Rhino 平臺的研發任務,還會配合 QA&RD 來完成公司大型項目,重點業務的性能壓測工作。

          4.1 重大項目支撐

          公司內重大項目的壓測,Rhino 平臺都會積極參與,全力支撐的。其中,比較典型的項目有抖音春晚,西瓜百萬英雄,春節紅包雨等活動。

          其中字節春節紅包雨活動,完成是由 Rhino 團隊來負責和完成的。字節春節紅包雨活動是在春節期間,所有字節客戶端發起的,諸如抽卡分現金,紅包錦鯉,紅包雨等一系列的超大規模的紅包引流活動。其流量規模巨大,流量突發性強,業務邏輯和網絡架構復雜度高等等,都對 Rhino 平臺提出不小的挑戰。

          在春節紅包雨活動中,所有用戶流量都經過運營商專線接入到網絡邊緣的匯聚機房,然后經過過濾和驗證后,再轉發到核心機房。其中各個 IDC 互為備份,其具體流量路線如圖。在這里,不僅要驗證后端各服務是否能承載預期流程,還要驗證各個專線帶寬,各個網關帶寬及轉發能力,各 IDC 承載能力以及之間帶寬等等。

          為此,我們將整個壓測拆分成多個階段,來簡化壓測復雜性,也降低壓測問題定位的難度:

          • 通過撥測/CDN 壓測來分別驗證各個匯聚機房的承載能力,帶寬,以及網關性能。
          • 在各個匯聚機房部署壓測 Agent,來模擬用戶流量分布,來壓測部署在核心機房的后端服務性能。
          • 單接口單實例壓測,單接口單機房壓測,場景化全鏈路單機房壓測,場景化全鏈路全資源壓測,分階段來驗證后端服務性能。
          • 最后會通過全網撥測,來模擬真實春節紅包雨高峰期流量,整體驗證全系統性能。

          在這些大型項目的支撐中,Rhino 團隊不僅學到了大量的業務和架構設計知識,還了解到業務研發同學如何看待壓測,如何使用平臺,幫助我們發現更多平臺的問題,促進平臺不斷迭代優化。

          4.2 日常壓測任務支撐

          日常壓測支撐,也是 Rhino 平臺非常重要的一項任務。對于日常壓測中遇到的各種問題,我們采用了各種方案來解決:

          • 專人 Oncall 值周,一對一指導。
          • 詳細完善的壓測知識庫,不僅介紹了平臺如何使用,還包括壓測如何改造,壓測方案如何制定,壓測問題如何定位。
          • 完善的性能培訓體系:定期開展性能測試相關分享,并對于 QA&RD 團隊,也會開展專業的壓測培訓。

          4.3 線上流量調度

          Rhino 平臺還實現了線上流量的定期調度,以達到線上實例自動壓測的目的[8]:

          • 將線上流量逐步調度到目標實例上,來測試服務實例性能極限,并給出實例性能 Profile,分析出實例性能瓶頸。
          • 通過長期的流量調度,來觀察服務實例性能變化,以監控服務性能的變化趨勢。
          • 通過不同資源水位下的實例性能,來預估出整個集群容量。完成對服務容量預估,以及線上風險評估。
          • 基于泳道化的流量調度,可以精確的預估服務集群容量。

          其具體實現方案如下:

          • 修改負載均衡中目標實例的權重 Weight 值,逐步調大該 Weight 值,將更多流量集中打到目標實例,直到達到設置的停止閾值。

          目前已經有 500+微服務接入,每天定時執行流量調度,來監控線上服務性能變化趨勢,如下圖。

          4.4 常態化壓測

          Rhino 平臺目前還在公司內推行常態化壓測,通過周期定時化的自動化全鏈路壓測,來實現以下目標:

          • 實時監控線上服務集群容量,防止服務性能劣化。
          • 實時監控線上鏈路容量,防止鏈路性能劣化。

          目前 Rhino 平臺上的常態化壓測,會周期定時,以無人值守的方式,自動執行壓測任務,并推送壓測結果。在壓測執行過程中,會根據調用鏈自動完成壓測開關開啟,發起壓測流量。實時監控服務性能指標,并根據 Metric 及告警監控,自動完成壓測熔斷,以保證壓測安全。

          目前已經有多個業務方接入常態化壓測,以此保證線上服務的穩定性。

          4.5 DevOps 流水線中的壓測

          服務在上線時,都會經過預發布,線上小流量灰度,線上全量發布。在這個過程中,我們可以通過線上測試 Case 以及灰度發布,來攔截服務線上功能缺陷。但是對于性能缺陷的攔截,卻不夠有效。

          從線上故障跟蹤系統里就可以發現,由于上線前沒有做好性能壓測,很多性能缺陷都逃逸到了線上。

          為了攔截各種性能缺陷,Rhino 平臺完成了 DevOps 平臺的打通。將壓測服務在 DevOps 平臺上注冊成一個原子服務 ,研發人員可以將壓測節點編排在任意流水線的任意位置,實現上線前的例行壓測。DevOps 流水線中的壓測,不僅可以幫助 RD 發現代碼中的性能問題,還能與性能基線進行 Diff,來發現代碼性能變壞的味道。

          5. 總結與展望

          5.1 總結

          Rhino 壓測平臺從立項到現在,不到兩年的時間內,其發展已經初具規模,如圖(每月壓測執行統計)。這個期間,非常非常感謝公司內所有合作團隊,尤其是架構團隊,中臺團隊對壓測平臺的支撐,沒有他們的支撐,全鏈路壓測建設是難以完成的。

          5.2 未來發展

          業務深層次定制化

          通用壓測平臺已經初步搭建完成,基本上能滿足業務線日常壓測需求。但在日常壓測支撐過程中,發現不同業務線在壓測時,但是仍然有大量的前置和后繼工作需要人工來完成。

          如何更進一步降低業務方壓測改造的成本,如何減少壓測環境數據預置成本,如何快速完成壓測數據清理,如何快速定位出性能問題等等,Rhino 壓測平臺后續將更進一步深入業務,與各大業務方開展更深入的合作,提供更深度的業務定制,為研發提效,助力業務線發展。

          壓測與容量規劃

          業務目前資源是否充足,其具體容量是多少;按照目前業務增長,其機器資源還能支撐多久?

          目前服務資源利用如何,是否可以優化,如何更進一步提升資源利用率,降低機器資源成本?

          某大型活動,需要申請多少資源?是否不需要壓測,或者自動化利用線上流量數據,或者利用日常壓測數據,就可以給出上述問題的結論?

          壓測與 SRE

          如何保證服務穩定性,如何監控服務性能劣化并及時預警,限流、超時、重試以及熔斷等服務治理措施配置是否合理?以及如何配合混沌測試進行容災演練,保證服務穩定性等等,這些 Rhino 平臺都會做更進一步探索。

          6. 招聘

          目前 Rhino 團隊還非常小,非常缺少性能測試以及后端開發相關的研發工程師,歡迎感興趣的同學來加入。簡歷投遞郵箱: tech@bytedance.com ;郵件標題: 姓名 - 工作年限 - Rhino 。

          參考文獻

          [1] http://jm.taobao.org/2017/03/30/20170330/

          [2] https://testerhome.com/topics/19493

          [3] https://tech.meituan.com/2018/09/27/quake-introduction.html

          [4] https://tech.meituan.com/2019/02/14/full-link-pressure-test-automation.html

          [5] https://www.open-open.com/lib/view/open1484317425690.html

          [6] https://www.infoq.cn/article/NvfJekpvU154pwlsCTLW

          [7] https://tech.bytedance.net/articles/3199

          [8] https://www.usenix.org/conference/osdi16/technical-sessions/presentation/veeraraghavan

          更多分享

          Fastbot:行進中的智能 Monkey

          品質優化 - 圖文詳情頁秒開實踐

          Android Camera 內存問題剖析

          字節跳動自研線上引流回放系統的架構演進


          歡迎關注「字節跳動技術團隊」

          得不佩服,美觀小巧的網頁內容編輯器——ContentTools


          愛分享Coder

          2019-12-03 · 軟件開發工程師 優質科技領域創作者

          介紹

          ContentTools是一個美觀小巧的網頁內容工具(一個JS庫),具備所見即所得(WYSIWYG)的編輯器功能,只需幾個簡單的步驟,即可將ContentTools添加到任何HTML頁面。如下圖所示頁面通過實時ContentTool的彈出層實現實時編輯功能。用小而美來形容它最好不過了!

          Github地址

          https://github.com/GetmeUK

          特性

          ContentTools是用于HTML頁面的美觀小巧的內容編輯器。它被設計為:

          • 與框架無關的庫不使用任何JavaScript框架(沒有JQuery),但可以很好地使用它們。
          • 靈活的ContentTools軟件包由5個庫組成,每個庫或可以獨立使用。
          • 可擴展的軟件包旨在易于擴展。
          • 小巧完整的編輯器(JS,CSS,圖像和圖標字體)為241kb(壓縮后為49kb)。

          功能簡介

          ContentTools具有字體加粗、斜體、超鏈接、對齊、列表、表格、圖片、視頻、代碼、撤銷、重做、刪除等功能

          1、加粗顯示

          2、斜體顯示

          3、超鏈接

          4、H標題

          5、正文

          6、有序和無序列表

          7、插入表格

          8、插入圖片

          9、視頻

          以上截圖中的功能還不完整,如果想體驗以下完整的功能可以直接去DEMO頁面體驗,如果需要在HTML級別上更改元素的內容,那也是可以的。通過屬性對話框中的最后一個選項卡,可以查看所選元素的內部HTML代碼并直接對其進行更新。

          使用

          • 第一步是下載JS,CSS和其他關聯的項目文件:

          下載倉庫并打開/ build文件夾,包括預構建的源文件。將文件夾的內容復制到項目的適當位置(例如,content-tools.min.js>

          /www/scripts/content-tools.min.js)。但是,/ images文件夾和icons.woff字體需要復制到與content-tools.min.css相同的文件夾中,文件結構應類似于:

          • HTML

          <head>

          <title>My page</title>

          <link rel="stylesheet" type="text/css" href="assets/content-tools.min.css">

          ...

          </head>

          <body>

          ...

          <script src="assets/content-tools.min.js"></script>

          <script src="assets/editor.js"></script>

          </body>

          包括一個名為editor.js的附加JS文件。包含初始化我們的編輯器的代碼,繼續

          <div data-editable data-name="main-content">

          <blockquote>

          Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.

          </blockquote>

          <p>John F. Woods</p>

          </div>

          data-name屬性用于在保存時標識區域(默認情況下使用id屬性),標記可編輯HTML時,常見的誤解是將單個元素標記為可編輯,例如:

          <h1 data-editable data-name="heading">Content</h1>

          正確的使用方式如下,也就是說必須要在特定的容器元素內

          <div data-editable data-name=heading>

          <h1>Content</h1>

          </div>

          • 準備CSS

          ContentTools使用CSS類來對齊文本,圖像,視頻和iframe,需要在自己的CSS中為這些對齊類定義樣式,例如:

          [data-editable] iframe,

          [data-editable] image,

          [data-editable] [data-ce-tag=img],

          [data-editable] img,

          [data-editable] video {

          clear: both;

          display: block;

          margin-left: auto;

          margin-right: auto;

          max-width: 100%;

          }

          /* 左對齊 */

          [data-editable] .align-left {

          clear: initial;

          float: left;

          margin-right: 0.5em;

          }

          /* 右對齊 */

          [data-editable].align-right {

          clear: initial;

          float: right;

          margin-left: 0.5em;

          }

          /* 可編輯區域中文本的對齊樣式 */

          [data-editable] .text-center {

          text-align: center;

          }

          [data-editable] .text-left {

          text-align: left;

          }

          [data-editable] .text-right {

          text-align: right;

          }

          • 初始化編輯器

          ContentTools提供了一個編輯器,但是在初始化它之前,我們需要配置一些東西,即:

          1. 我們希望用戶能夠將CSS樣式應用于元素。
          2. 我們希望頁面的區域是可編輯的。
          3. 一種保存我們的內容的機制。
          4. 我們可能還會配置圖像處理程序等等

          將以下代碼添加到我們之前創建的editor.js文件中:

          window.addEventListener('load', function() {

          var editor;

          });

          • 配置樣式

          就像文字處理程序一樣,可以為內容配置一系列預定義樣式。當用戶從視口底部的檢查器欄中選擇標簽時,這些標簽就會出現。盡管可以將樣式設置為適用于所有標簽,但是僅顯示適用于標簽類型的樣式。

          我們將添加可應用于段落<p>標記的單一樣式.author。在var編輯器下方聲明添加:

          ContentTools.StylePalette.add([

          new ContentTools.Style('Author', 'author', ['p'])

          ]);

          StylePalette.add方法使我們可以向編輯器添加樣式列表。每種樣式均聲明為一個Style實例,該實例使用顯示名稱,CSS類和可以應用該樣式的標簽列表初始化。我們需要添加相關的CSS來支持這種樣式,因此在HTML的開頭添加:

          <head>

          ...

          <style>

          .author {

          font-style: italic;

          font-weight: bold;

          }

          </style>

          </head>

          • 選擇可編輯區域

          接下來,我們需要初始化編輯器,并讓它知道頁面上的哪些元素是可編輯的。為此,將以下代碼添加到editor.js中:

          editor=ContentTools.EditorApp.get();

          editor.init('*[data-editable]', 'data-name');

          我們使用用于頁面可編輯區域的CSS選擇器和屬性名稱(“數據名稱”)來初始化編輯器,以告知編輯器元素的哪個屬性包含其區域名稱。區域名稱在同一頁面中必須唯一。

          • 保存更改

          最后,我們希望在用戶保存頁面時得到通知,以便我們可以將每個區域的更新內容存儲在文件或數據庫中。為此,我們監聽由編輯器觸發的保存事件。在editor.init語句之后,將以下代碼添加到editor.js中:

          editor.addEventListener('saved', function (ev) {

          var name, payload, regions, xhr;

          // 檢查是否已更改

          regions=ev.detail().regions;

          if (Object.keys(regions).length==0) {

          return;

          }

          // 保存更改時將編輯器設置為忙

          this.busy(true);

          // 將每個區域的內容收集到一個FormData實例中

          payload=new FormData();

          for (name in regions) {

          if (regions.hasOwnProperty(name)) {

          payload.append(name, regions[name]);

          }

          }

          // 將更新內容發送到要保存的服務器

          function onStateChange(ev) {

          // 檢查請求是否完成

          if (ev.target.readyState==4) {

          editor.busy(false);

          if (ev.target.status=='200') {

          // 保存成功,通知前臺

          new ContentTools.FlashUI('保存成功');

          } else {

          // 保存失敗,通知前臺

          new ContentTools.FlashUI('保存失敗');

          }

          }

          };

          xhr=new XMLHttpRequest();

          xhr.addEventListener('readystatechange', onStateChange);

          xhr.open('POST', '/save-my-page');

          xhr.send(payload);

          });

          當用戶保存頁面時,我們可以使用AJAX將每個區域的內容發送到服務器進行保存。在瀏覽器中打開頁面,尋找左上方的藍色編輯按鈕,然后單擊它以開始編輯。





          總結

          這樣一個美觀且強大的即時編輯器可謂是非常的實用,特別是對于一些內容編輯網站,如CMS、靜態文檔網站、博客等內容型網站尤其有用,希望對你有所幫助,Enjoy it!

          1.5萬閱讀

          搜索

          專門制作文字特效軟件

          網站制作微信小程序

          html5編輯軟件排行榜

          傻瓜式網頁制作軟件

          網站制作軟件免費版

          一鍵網站制作app

          實現css兩端對齊,我在網上找了很多方法,都不怎么實用,都是兼容性鬧得,column是css3的屬性,是多列布局,使用column來實現兩端對齊簡單實用,就要設置下模塊的個數跟column的列數一致就行,先看它的的3個屬性:

          1.column-count 屬性規定元素應該被分隔的列數

          2.column-gap 屬性規定列之間的間隔

          2.column-rule 屬性設置列之間的寬度、樣式和顏色規則。

          CSS3 多列屬性的兼容性:Internet Explorer 10 和 Opera 支持多列屬性,Firefox 需要前綴 -moz-,Chrome 和 Safari 需要前綴 -webkit-,特別注意:Internet Explorer 9 以及更早的版本不支持多列屬性。

          實現css兩端對齊的例子:用column-count定義對象的列數,例子中有4個p(即4個模塊),那么就定義為4列,再用column-gap定義了對象中列與列的間距,間距不能設置為百分比,但是只能用px,具體的看下面的代碼:

          <!Doctype html>

          <html>

          <head>

          <meta http-equiv="Content-Type" content="text/html; charset=gbk2312"/>

          <title>實現css兩端對齊</title>

          <style type="text/css">

          *{margin:0;padding:0;}

          .box{

          margin:100px 0;

          -webkit-column-count:4;-moz-column-count:4;column-count:4;

          -webkit-column-gap:30px;-moz-column-gap:30px;column-gap:30px;

          }

          .box p{

          height:30px;

          line-height:30px;

          text-align:center;

          border:1px solid red;

          color:#000;

          font-size:12px;

          }

          </style>

          </head>

          <body>

          <div class="box">

          <p>第1列</p>

          <p>第2列</p>

          <p>第3列</p>

          <p>第4列</p>

          </div>

          </body>

          </html>

          點擊查看css兩端對齊效果(http://tangjiusheng.com/css3/column.html)

          除注明外的文章,均為來源:湯久生博客,轉載請保留本文地址!

          原文地址:http://tangjiusheng.com/css3/130.html


          主站蜘蛛池模板: 久久99国产一区二区三区| 国产情侣一区二区三区| 中文字幕久久亚洲一区 | 精品无码国产一区二区三区51安| 国产伦精品一区二区三区无广告 | 国产成人高清亚洲一区91| 亚洲AV乱码一区二区三区林ゆな| 日本免费一区二区三区最新vr| 91在线视频一区| 久久国产免费一区| 亚洲一区二区三区自拍公司| 福利一区福利二区| 美女视频一区二区| 视频在线一区二区| 美女视频一区二区三区| 国产一区二区三区日韩精品| 99偷拍视频精品一区二区| 亚洲综合无码一区二区痴汉| 亚洲国产精品第一区二区| 奇米精品一区二区三区在线观看| 中文字幕一区二区三区视频在线| 丰满人妻一区二区三区视频| 午夜视频久久久久一区| 国产三级一区二区三区| 国产成人一区二区精品非洲| 国产精品一区电影| 丰满人妻一区二区三区视频| 中文字幕精品无码一区二区| 久久精品动漫一区二区三区| 久久er99热精品一区二区| 91在线视频一区| 无码中文字幕一区二区三区| 精品国产一区二区三区在线| 国产精品亚洲一区二区三区在线观看 | 亚洲国产成人一区二区精品区| 国产一区二区免费视频| 日韩精品一区二区三区中文| 在线日产精品一区| 四虎精品亚洲一区二区三区| 中文字幕一区二区三区四区| 色老头在线一区二区三区|