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 亚洲精品日本高清中文字幕,精品国产视频在线观看,日韩在线|中文

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          字節(jié)跳動(dòng)全鏈路壓測(cè)(Rhino)的實(shí)踐

          字節(jié)跳動(dòng)全鏈路壓測(cè)(Rhino)的實(shí)踐

          . 背景

          隨著公司業(yè)務(wù)的不斷擴(kuò)張,用戶流量在不斷提升,研發(fā)體系的規(guī)模和復(fù)雜性也隨之增加。線上服務(wù)的穩(wěn)定性也越來(lái)越重要,服務(wù)性能問(wèn)題,以及容量問(wèn)題也越發(fā)明顯。

          因此有必要搭建一個(gè)有效壓測(cè)系統(tǒng),提供安全、高效、真實(shí)的線上全鏈路壓測(cè)服務(wù),為線上服務(wù)保駕護(hù)航。

          關(guān)于全鏈路壓測(cè)的建設(shè),業(yè)界已經(jīng)有了非常多文章,但是涉及到具體的技術(shù)實(shí)現(xiàn)方面,卻很少介紹。本文想從全鏈路壓測(cè)系統(tǒng),從設(shè)計(jì)到落地整個(gè)實(shí)踐過(guò)程,來(lái)詳細(xì)介紹下全鏈路壓測(cè)系統(tǒng)是具體是如何設(shè)計(jì),以及如何落地的。希望能從技術(shù)落地實(shí)踐的角度,給同行業(yè)的同學(xué)一些參考和啟發(fā)。

          2. 解決方案

          2.1 業(yè)內(nèi)實(shí)踐

          全鏈路壓測(cè)在業(yè)內(nèi)已經(jīng)有了廣泛的實(shí)踐,如阿里的 Amazon、PTS[1][2],美團(tuán)的 Quake[3][4],京東的的 ForceBOT[5],高德的 TestPG[6]等等,都為我們提供豐富的實(shí)踐經(jīng)驗(yàn),和大量?jī)?yōu)秀的技術(shù)方案。我們廣泛吸收了各大互聯(lián)網(wǎng)公司的全鏈路壓測(cè)建設(shè)經(jīng)驗(yàn),并基于字節(jié)跳動(dòng)業(yè)務(wù)需求,設(shè)計(jì)開發(fā)了一個(gè)全鏈路壓測(cè)系統(tǒng) Rhino。

          2.1 架構(gòu)圖

          Rhino 平臺(tái)作為公司級(jí)的全鏈路壓測(cè)平臺(tái),它的目標(biāo)是對(duì)全公司所有業(yè)務(wù),提供單服務(wù)、全鏈路,安全可靠、真實(shí)、高效的壓測(cè),來(lái)幫助業(yè)務(wù)高效便捷的完成性能測(cè)試任務(wù),更精確評(píng)估線上服務(wù)性能&容量方面風(fēng)險(xiǎn)。

          因此在 Rhino 平臺(tái)設(shè)計(jì)之初,我們就定下以下目標(biāo):

          • 安全:所有壓測(cè)都是在線上完成的,所以理論上所有的壓測(cè)對(duì)線上用戶都是有損的。壓測(cè)平臺(tái)將從服務(wù)狀態(tài),以及壓測(cè)數(shù)據(jù)兩方面去保證壓測(cè)的安全性。
          • 高效:較少壓測(cè)腳本編寫成本,數(shù)據(jù)構(gòu)造和壓測(cè)監(jiān)控成本,盡量自動(dòng)化完成壓測(cè)過(guò)程的各個(gè)階段。
          • 準(zhǔn)確:精確的壓力控制,準(zhǔn)確的鏈路壓測(cè)監(jiān)控,精確的壓測(cè)報(bào)告結(jié)果,以及性能&容量數(shù)據(jù)。
          • 高覆蓋:需要支撐公司內(nèi)不同的業(yè)務(wù)線的壓測(cè)需求,如搜索,廣告,電商,教育,游戲等等。

          Rhino 是一個(gè)分布式全鏈路壓測(cè)系統(tǒng),可以通過(guò)水平擴(kuò)展,來(lái)實(shí)現(xiàn)模擬海量用戶真實(shí)的業(yè)務(wù)操作場(chǎng)景,對(duì)線上各種業(yè)務(wù)進(jìn)行全方位的性能測(cè)試。它主要分為控制中心(Rhino Master)模塊,壓測(cè)鏈路服務(wù)模塊,監(jiān)控系統(tǒng)模塊,壓測(cè)引擎模塊,如圖。(每一個(gè)模塊都是由多個(gè)微服務(wù)來(lái)完成的。如下圖每個(gè)實(shí)線圖都代表一個(gè)微服務(wù)或多個(gè)微服務(wù))。

          3. 核心功能介紹

          • 搭建全鏈路壓測(cè)平臺(tái),最核心主要有:數(shù)據(jù)構(gòu)造、壓測(cè)隔離、鏈路治理、任務(wù)調(diào)度、壓測(cè)熔斷、壓測(cè)引擎、壓測(cè)監(jiān)控等。下面我們將從這些方面詳細(xì)介紹下,在 Rhino 平臺(tái)中是如何設(shè)計(jì)和實(shí)現(xiàn)的。

          3.1 數(shù)據(jù)構(gòu)造

          壓測(cè)過(guò)程中數(shù)據(jù)構(gòu)造是最重要,也是最為復(fù)雜的環(huán)節(jié)。壓測(cè)數(shù)據(jù)的建模,直接影響了壓測(cè)結(jié)果的準(zhǔn)確性。

          • 對(duì)于服務(wù)性能缺陷掃描,性能調(diào)優(yōu),以及新上線服務(wù),推薦構(gòu)造 Fake 數(shù)據(jù),來(lái)壓測(cè)指定路徑。
          • 對(duì)于線上容量規(guī)劃,性能能力驗(yàn)證,以及性能 Diff,推薦使用線上真實(shí)流量,使壓測(cè)結(jié)果更貼近真實(shí)情況。
          • 對(duì)于涉及到用戶賬號(hào),用戶登錄態(tài)保持的情況,推薦使用壓測(cè)專屬測(cè)試賬號(hào),避免影響線上真實(shí)用戶。

          基礎(chǔ)數(shù)據(jù)構(gòu)造

          為了高效的構(gòu)造特定的 Fake 壓測(cè)數(shù)據(jù),Rhino 壓測(cè)平臺(tái)提供大量數(shù)據(jù)構(gòu)造方式:

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

          壓測(cè)賬號(hào)

          在壓測(cè)過(guò)程中,有些壓測(cè)請(qǐng)求需要進(jìn)行登錄,并保持會(huì)話;此外在很多壓測(cè)請(qǐng)求中涉及到用戶賬號(hào)信息 UserID,DeviceID 等數(shù)據(jù)。用戶賬號(hào)的構(gòu)造問(wèn)題,一直是壓測(cè)過(guò)程中非常棘手的問(wèn)題。Rhino 平臺(tái)打通的用戶中心,設(shè)置了壓測(cè)專屬的賬號(hào)服務(wù),完美地解決了壓測(cè)過(guò)程中的登錄態(tài),以及測(cè)試賬號(hào)等問(wèn)題。具體流程和使用界面,如下圖。

          3.2 壓測(cè)隔離

          壓測(cè)隔離中需要解決的壓測(cè)流量隔離,以及壓測(cè)數(shù)據(jù)的隔離。

          壓測(cè)流量隔離,主要是通過(guò)構(gòu)建壓測(cè)環(huán)境來(lái)解決,如線下壓測(cè)環(huán)境,或泳道化/Set 化建設(shè),將壓測(cè)流量與線上流程完全隔離。優(yōu)點(diǎn)是壓測(cè)流量與線上流量完全隔離,不會(huì)影響到線上用戶。缺點(diǎn):機(jī)器資源及維護(hù)成本高,且壓測(cè)結(jié)果需要經(jīng)過(guò)一定的換算,才能得線上容量,結(jié)果準(zhǔn)確性存在一定的問(wèn)題。目前公司內(nèi)壓測(cè)都是在線上集群上完成的,線上泳道化正在建設(shè)中。

          壓測(cè)數(shù)據(jù)隔離,主要是通過(guò)對(duì)壓測(cè)流量進(jìn)行染色,讓線上服務(wù)能識(shí)別哪些是壓測(cè)流量,哪些是正常流量,然后對(duì)壓測(cè)流量進(jìn)行特殊處理,以達(dá)到數(shù)據(jù)隔離的目的。目前 Rhino 平臺(tái)整體壓測(cè)隔離框架如圖。

          壓測(cè)標(biāo)記

          壓測(cè)標(biāo)記就是最常見的壓測(cè)流量染色的方式。

          • 對(duì)于 RPC 協(xié)議,會(huì)在請(qǐng)求的頭部中增加一個(gè) Key:Value 的字段作為壓測(cè)標(biāo)記。
          • 對(duì)于 HTTP 和其他協(xié)議,會(huì)在請(qǐng)求頭,自動(dòng)注入一個(gè) Stress 標(biāo)記(Key-Value) 。
          • 壓測(cè)標(biāo)記 Key:Value,其中 key 是固定的 Stress_Tag 值,但是每個(gè)壓測(cè)任務(wù)都有唯一的 Stress_Value 值,主要用于解決壓測(cè)數(shù)據(jù)沖突,以及性能問(wèn)題定位。

          壓測(cè)標(biāo)記透?jìng)?/strong>

          目前公司內(nèi)各個(gè)基礎(chǔ)組件、存儲(chǔ)組件,以及 RPC 框架都已經(jīng)支持了壓測(cè)標(biāo)記的透?jìng)鳌F湓硎菍簻y(cè)標(biāo)記的 KV 值存入 Context 中,然后在所有下游請(qǐng)求中都帶上該 Context,下游服務(wù)可以根據(jù) Context 中壓測(cè)標(biāo)記完成對(duì)壓測(cè)流量的處理。在實(shí)際業(yè)務(wù)中,代碼改造也非常簡(jiǎn)單,只需要透?jìng)?Context 即可。

          Golang 服務(wù): 將壓測(cè)標(biāo)記寫入 Context 中。

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

          Java 服務(wù):利用 ThreadLocal 存儲(chǔ)線程 Context。

          壓測(cè)開關(guān)

          為了解決線上壓測(cè)安全問(wèn)題,我們還引入了壓測(cè)開關(guān)組件。

          • 每個(gè)服務(wù)每個(gè)集群,都有一個(gè)壓測(cè)開關(guān)。只有打開壓測(cè)開關(guān)時(shí),壓測(cè)流量才能流入到服務(wù)內(nèi),否則就會(huì)被底層微服務(wù)框架直接拒絕,業(yè)務(wù)層無(wú)感知。
          • 在每個(gè) IDC 區(qū)域,都會(huì)有一個(gè)全局的壓測(cè)總開關(guān)。只有打開了這個(gè)全局壓測(cè)開關(guān),壓測(cè)流量才被允許在這個(gè) IDC 內(nèi)流轉(zhuǎn)。
          • 當(dāng)線上出現(xiàn)壓測(cè)問(wèn)題,除了從源頭關(guān)閉壓測(cè)流量以外,關(guān)閉目標(biāo)服務(wù)的壓測(cè)開關(guān),也能立即阻斷壓測(cè)流量。

          壓測(cè)數(shù)據(jù)隔離

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

          Rhino 平臺(tái)針對(duì)不同存儲(chǔ),有不同的解決方案:

          • MySQL、MongoDB:影子表。SDK 判斷是否是壓測(cè)流量,若是則根據(jù)配置映射至新表名。配置策略有兩種,一是讀寫影子表,二是讀線上表、寫影子表。
          • Redis:Redis Key 加上 Stress 前綴。如 Stress_Tag=Valuex,那么讀寫 Redis 的 Key=Valuex_Key。這樣可以解決多個(gè)壓測(cè)任務(wù)數(shù)據(jù)沖突的問(wèn)題。壓測(cè)結(jié)束后,只需要對(duì) Prefix=Valuex 做清除或過(guò)期操作即可。
          • MQ:對(duì)于消息隊(duì)列,Rhino 平臺(tái)有兩種策略。一是直接丟棄,然后針對(duì)消息隊(duì)列的性能,單獨(dú)進(jìn)行壓測(cè);二是在 Header 中透?jìng)鲏簻y(cè)標(biāo)記,Consumer 根據(jù)壓測(cè)標(biāo)記和業(yè)務(wù)需求,再做特殊處理。默認(rèn)走丟棄策略,業(yè)務(wù)方可根據(jù)需求進(jìn)行配置。
          • 其他存儲(chǔ),如 ES,ClickHouse 等,都有壓測(cè)集群。壓測(cè)時(shí),會(huì)將壓測(cè)請(qǐng)求打到指定的壓測(cè)集群中。

          服務(wù)壓測(cè)改造

          在壓測(cè)之前,需要對(duì)服務(wù)進(jìn)行壓測(cè)驗(yàn)證。對(duì)于不滿足壓測(cè)要求(即壓測(cè)數(shù)據(jù)隔離)的服務(wù),需要進(jìn)行壓測(cè)改造。

          1. 壓測(cè)驗(yàn)證:對(duì)于存儲(chǔ)服務(wù),在不打開壓測(cè)開關(guān)的前提下,通過(guò)壓測(cè)請(qǐng)求,發(fā)送讀寫操作都是會(huì)被拒絕。如果沒(méi)有拒絕,說(shuō)明在操作存儲(chǔ)服務(wù)時(shí),沒(méi)有帶上壓測(cè) Context,需要進(jìn)行改造。
          2. 壓測(cè)改造:壓測(cè)改造是線上全鏈路壓測(cè)推進(jìn)中非常關(guān)鍵,而又非常困難的一個(gè)環(huán)節(jié)。對(duì)于已經(jīng)上線的服務(wù),壓測(cè)改造還極有可能會(huì)引入新的 BUG,所以經(jīng)常推動(dòng)起來(lái)比較困難。因此為了解決這些問(wèn)題,Rhino 平臺(tái)有以下幾個(gè)解決方案:

          a. 盡量減少代碼改動(dòng),并給出完整的指導(dǎo)手冊(cè)及代碼示例,減少 RD 的工作量,降低代碼錯(cuò)誤的可能性

          b. 提供簡(jiǎn)單便捷的線上線下 HTTP&RPC 的壓測(cè)請(qǐng)求 Debug 工具,方便代碼改動(dòng)的驗(yàn)證

          c. 對(duì)于新項(xiàng)目,在項(xiàng)目開始初期,就將壓測(cè)改造加入項(xiàng)目開發(fā)規(guī)范中,減少后期的代碼改動(dòng)

          3.3 鏈路治理

          鏈路梳理

          請(qǐng)求調(diào)用鏈,對(duì)于線上壓測(cè)是非常重要的:

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

          Rhino 平臺(tái)通過(guò)公司的流式日志系統(tǒng)來(lái)完成調(diào)用鏈檢索的。一個(gè)服務(wù)在被請(qǐng)求或者請(qǐng)求下游時(shí),都會(huì)透?jìng)饕粋€(gè) LogID。RPC 框架會(huì)打印調(diào)用鏈日志(包括 RPC 日志-調(diào)用者日志,Access 日志-被調(diào)用者日志),所有日志中都會(huì)包含這個(gè) LogID。通過(guò) LogID 將一個(gè)請(qǐng)求所經(jīng)過(guò)的所有服務(wù)日志串起來(lái),就完成調(diào)用鏈檢索。

          Rhino 平臺(tái)在公司流式日志系統(tǒng)提供的鏈路梳理功能基礎(chǔ)上,進(jìn)行了進(jìn)一步優(yōu)化,以滿足壓測(cè)需要:

          • 自動(dòng)梳理:由于公司采用微服務(wù)架構(gòu),每個(gè)請(qǐng)求背后的調(diào)用鏈路及其復(fù)雜,單純靠人工維護(hù)是無(wú)法完成的。 用戶只需要提供請(qǐng)求中 LogID,Rhino 平臺(tái)就能快速梳理出該請(qǐng)求經(jīng)過(guò)的服務(wù)節(jié)點(diǎn),如圖。
          • 實(shí)時(shí)梳理:由于線上服務(wù)不斷在變化,上線下線新增等,因此同一個(gè)請(qǐng)求的調(diào)用鏈也是不斷變化的。Rhino 平臺(tái)建議一般使用 1 個(gè)小時(shí)內(nèi)的 LogID 進(jìn)行梳理。
          • 多調(diào)鏈路合并:同一個(gè)接口,不同參數(shù)下的調(diào)用鏈?zhǔn)遣槐M相同的。Rhino 平臺(tái)會(huì)將多個(gè) LogID 梳理的結(jié)果自動(dòng)進(jìn)行合并,來(lái)補(bǔ)全調(diào)用鏈,保證鏈路梳理結(jié)果的準(zhǔn)確性和完整性。

          測(cè)周知

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

          • 一鍵拉群:梳理完鏈路后,在壓測(cè)前可以一鍵拉群,將鏈路中上下游服務(wù)的 Owner 拉到同一個(gè)群里,同步壓測(cè)信息。
          • 壓測(cè)周知:每個(gè)壓測(cè)開始執(zhí)行時(shí),都會(huì)向壓測(cè)周知群里推送消息,如壓測(cè) QPS,壓測(cè)時(shí)長(zhǎng)等信息。

          • 壓測(cè)事件:在壓測(cè)開始執(zhí)行時(shí),Rhino 平臺(tái)還會(huì)向目標(biāo)服務(wù)的事件隊(duì)列中發(fā)送一個(gè)壓測(cè)事件,方便快速評(píng)估/定位穩(wěn)定性問(wèn)題是否是壓測(cè)導(dǎo)致,減少 RD 線上問(wèn)題排查的干擾。

          壓測(cè)開關(guān)管理

          在壓測(cè)之前,需要開啟整體鏈路的壓測(cè)開關(guān)的,否則壓測(cè)流量就會(huì)被服務(wù)拒絕,導(dǎo)致壓測(cè)失敗。

          • 一鍵開啟:在壓測(cè)執(zhí)行之前,Rhino 平臺(tái)可以一鍵開啟鏈接上所有節(jié)點(diǎn)的壓測(cè)開關(guān)。
          • 壓測(cè)開關(guān)開啟周知:壓測(cè)開關(guān)開啟時(shí),Rhino 平臺(tái)會(huì)自動(dòng)給對(duì)應(yīng)服務(wù) Owner 推送相關(guān)信息,確保服務(wù) Owner 了解相關(guān)壓測(cè)信息,上游會(huì)有壓測(cè)流量會(huì)經(jīng)過(guò)其服務(wù)。
          • 靜默關(guān)閉:壓測(cè)開關(guān)到期后,Rhino 會(huì)自動(dòng)靜默關(guān)閉壓測(cè)開關(guān),以保證線上服務(wù)的安全。

          服務(wù) Mock

          對(duì)于調(diào)用鏈中不能壓測(cè)的服務(wù)(敏感服務(wù)),或者第三方服務(wù),為了壓測(cè)請(qǐng)求的完整性,就需要對(duì)這些服務(wù)進(jìn)行 Mock。業(yè)界通用的 Mock 方案有:

          1. 修改業(yè)務(wù)代碼,修改服務(wù)調(diào)用為空轉(zhuǎn)代碼。優(yōu)點(diǎn):實(shí)現(xiàn)成本低。 缺點(diǎn):返回值固定,代碼&業(yè)務(wù)入侵高,推動(dòng)困難。如要 Mock 位置比較靠下游,超出部門覆蓋業(yè)務(wù)范圍,推動(dòng)就非常麻煩。
          2. 通用 Mock 服務(wù)。通用 MockServer,會(huì)根據(jù)不同用戶配置不同 Mock 規(guī)則,執(zhí)行對(duì)應(yīng)的響應(yīng)延時(shí),并返回對(duì)應(yīng)響應(yīng)數(shù)據(jù)。優(yōu)點(diǎn):無(wú)代碼入侵,業(yè)務(wù)方無(wú)感知。 缺點(diǎn):實(shí)現(xiàn)成本高。

          由于字節(jié)整個(gè)公司都采用微服務(wù)架構(gòu),導(dǎo)致一次壓測(cè)涉及鏈路都比較長(zhǎng),快速無(wú)業(yè)務(wù)入侵的 Mock

          方式成為了首選。Rhino 平臺(tái)是通過(guò)公司 Service Mesh 和 ByteMock 系統(tǒng)來(lái)實(shí)現(xiàn)了高效的,對(duì)業(yè)務(wù)透明的服務(wù) Mock。

          壓測(cè)執(zhí)行前,Rhino 平臺(tái)需要向 Service Mesh 注冊(cè)染色轉(zhuǎn)發(fā)規(guī)則,并向 Mock 服務(wù)注冊(cè) Mock 規(guī)則。然后在壓測(cè)流量中注入 Mock 染色標(biāo)記,才能完成服務(wù) Mock:

          1. 基于 Service Mesh 的染色流量轉(zhuǎn)發(fā)。首先需要在壓測(cè)流量中注入轉(zhuǎn)發(fā)染色標(biāo)記,并在 Service Mesh 中注冊(cè)對(duì)應(yīng)的轉(zhuǎn)發(fā)規(guī)則。Service Mesh 檢測(cè)到染色流量后,就會(huì)將其轉(zhuǎn)發(fā)到指定的 Mock Server 上,如圖。
          2. 基于 Mock Server 的請(qǐng)求規(guī)則匹配。首先在 Mock Server 上注冊(cè) Mock 規(guī)則,以及匹配的 Response 和響應(yīng)時(shí)延。當(dāng) Mock Server 接收到請(qǐng)求后,會(huì)根據(jù)規(guī)則進(jìn)行響應(yīng),如圖。

          3.4 發(fā)壓模式

          最小調(diào)度單元

          Rhino 平臺(tái)中,壓測(cè) Agent 就是一個(gè)最小調(diào)度單元。一次壓測(cè)任務(wù),通常會(huì)拆分成多個(gè)子 Job,然后下發(fā)到多個(gè) Agent 上來(lái)完成。

          • 最小化容器部署,減少資源浪費(fèi)。壓測(cè)對(duì)機(jī)器資源消耗是非常高的,通常 CPU &Memory 的使用率都在 80%以上。但是沒(méi)有壓測(cè)執(zhí)行時(shí)間內(nèi),機(jī)器資源使用率<5%。如果長(zhǎng)期占用大量的資源,將會(huì)對(duì)機(jī)器資源造成極大的浪費(fèi)。壓測(cè) Agent 都采用容器化部署,并且每個(gè)容器的資源規(guī)格也盡可能小,這樣既能滿足日常壓測(cè)需求,也不會(huì)占用太多的機(jī)器資源。
          • 獨(dú)占 Agent,增加壓測(cè)執(zhí)行穩(wěn)定性:?jiǎn)蝹€(gè)容器內(nèi)只啟動(dòng)一個(gè) Agent 進(jìn)程,單個(gè) Agent 同時(shí)只能被一個(gè)壓測(cè)任務(wù)占用,避免多任務(wù)多進(jìn)程的干擾和資源競(jìng)爭(zhēng),增加壓測(cè)的穩(wěn)定性。
          • 動(dòng)態(tài)擴(kuò)容,支撐海量 QPS 發(fā)壓:壓測(cè)高峰期,Rhino 平臺(tái)會(huì)臨時(shí)申請(qǐng)機(jī)器資源,快速擴(kuò)容,完成海量 QPS 的支撐。壓測(cè)完成后,會(huì)立即釋放機(jī)器資源,減少資源浪費(fèi)。

          2020 年春節(jié)搶紅包壓測(cè)中,Rhino 臨時(shí)擴(kuò)容在 4000+個(gè)實(shí)例,支撐了單次 3kw+QPS 的壓測(cè),但日常 Rhino 平臺(tái)只部署了 100+個(gè)實(shí)例,就能滿足日常壓測(cè)需求。

          智能壓力調(diào)節(jié)

          • 動(dòng)態(tài)分配壓測(cè) Agent:在壓測(cè)過(guò)程,經(jīng)常出現(xiàn)壓測(cè) Agent 的 CPU/Memory 使用率過(guò)高(>90%),導(dǎo)致壓力上不去,達(dá)不到目標(biāo) QPS;或者壓測(cè)延時(shí)過(guò)高,壓測(cè)結(jié)果不準(zhǔn)確的問(wèn)題。Rhino 平臺(tái)在發(fā)壓的過(guò)程中,會(huì)實(shí)時(shí)監(jiān)控每個(gè)壓測(cè) Agent 的 CPU/Memory 使用率,當(dāng)超過(guò)閾值時(shí)(>90%),會(huì)動(dòng)態(tài)分配額外的 Agent,以降低每個(gè) Agent 的負(fù)載,保證壓測(cè)的穩(wěn)定性。
          • 智能調(diào)節(jié)壓力:在壓測(cè)過(guò)程,通常需要不斷的調(diào)節(jié) QPS 大小,以達(dá)到性能壓測(cè)目標(biāo)。這過(guò)程非常耗費(fèi)精力和時(shí)間。Rhino 平臺(tái),可以根據(jù)壓測(cè)任務(wù)設(shè)定的性能指標(biāo),智能調(diào)節(jié) QPS 大小,當(dāng)達(dá)到壓測(cè)目標(biāo)后,會(huì)自動(dòng)熔斷,停止壓測(cè)。

          壓測(cè)鏈路模擬

          Rhino 平臺(tái)默認(rèn)將全鏈路壓測(cè)分為公網(wǎng)壓測(cè)和內(nèi)網(wǎng)壓測(cè)。公網(wǎng)壓測(cè)主要 IDC 網(wǎng)絡(luò)帶寬,延時(shí),IDC 網(wǎng)關(guān)新建連接、轉(zhuǎn)發(fā)等能力;內(nèi)網(wǎng)壓測(cè),主要是壓測(cè)目標(biāo)服務(wù),目標(biāo)集群的 性能,容量等。

          • 對(duì)于內(nèi)網(wǎng)壓測(cè),默認(rèn)都要求同 IDC 內(nèi)發(fā)壓,減少網(wǎng)絡(luò)延時(shí)的干擾。
          • 對(duì)于公網(wǎng)壓測(cè),Rhino 平臺(tái)在公司 CDN 節(jié)點(diǎn)上都有部署 Agent 節(jié)點(diǎn),利用了 CDN 節(jié)點(diǎn)剩余計(jì)算能力,完成了公網(wǎng)壓測(cè)能力的建設(shè)。

          同城多機(jī)房,異地多機(jī)房

          Rhino 平臺(tái)在各個(gè) IDC 都有部署 Agent 集群。各個(gè) IDC 內(nèi)服務(wù)的壓測(cè),默認(rèn)會(huì)就近選擇壓測(cè) Agent,來(lái)減少網(wǎng)絡(luò)延時(shí)對(duì)壓測(cè)結(jié)果的干擾,使得壓測(cè)結(jié)果更精準(zhǔn),壓測(cè)問(wèn)題定位更簡(jiǎn)單。

          邊緣計(jì)算節(jié)點(diǎn) Agent

          除了多機(jī)房部署之外,Rhino 平臺(tái)還在邊緣計(jì)算節(jié)點(diǎn)上也部署了壓測(cè) Agent,來(lái)模擬各種不同地域不同運(yùn)營(yíng)商的流量請(qǐng)求,確保流量來(lái)源,流量分布更貼近真實(shí)情況。在 Rhino 平臺(tái)上可以選擇不同地域不同運(yùn)營(yíng)商,從全國(guó)各個(gè)地區(qū)發(fā)起壓測(cè)流量。

          3.5 壓測(cè)熔斷

          為了應(yīng)對(duì)線上壓測(cè)風(fēng)險(xiǎn),Rhino 平臺(tái)提供兩種熔斷方式,來(lái)應(yīng)對(duì)壓測(cè)過(guò)程中的突發(fā)事件,來(lái)降低對(duì)線上服務(wù)造成的影響。

          基于告警監(jiān)控的熔斷

          每個(gè)壓測(cè)任務(wù),都可以關(guān)聯(lián)調(diào)用鏈中任意服務(wù)的告警規(guī)則。在壓測(cè)任務(wù)執(zhí)行過(guò)程,Rhino 平臺(tái)會(huì)主動(dòng)監(jiān)聽告警服務(wù)。 當(dāng)調(diào)用鏈中有服務(wù)出現(xiàn)了告警,會(huì)立即停止壓測(cè)。對(duì)于沒(méi)有關(guān)聯(lián)的告警,Rhino 平臺(tái)也會(huì)記錄下來(lái),便于壓測(cè)問(wèn)題定位。

          基于 Metric 的熔斷

          自定義監(jiān)控指標(biāo)及閾值,到達(dá)閾值后,也會(huì)自動(dòng)停止壓測(cè)。目前支持 CPU、Memory、 上游穩(wěn)定性、錯(cuò)誤日志,以及其他自定義指標(biāo)。

          此外,除了 Rhino 平臺(tái)自身提供的熔斷機(jī)制以外,公司服務(wù)治理架構(gòu)也提供了很多額外的熔斷機(jī)制,如壓測(cè)開關(guān),一鍵切斷壓測(cè)流量;過(guò)載保護(hù),服務(wù)過(guò)載時(shí)自動(dòng)丟棄壓測(cè)流量。

          3.6 任務(wù)模型

          HTTP 任務(wù)

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

          RPC 任務(wù)

          對(duì)于 RPC 任務(wù),Rhino 也自動(dòng)完成了對(duì) IDL 的解析,然后轉(zhuǎn)換成 JSON 格式,便于用戶參數(shù)化處理。

          自定義-Go Plugin

          對(duì)于非 HTTP/RPC 的協(xié)議,以及有復(fù)雜邏輯的壓測(cè)任務(wù),Rhino 平臺(tái)也提供了完善的解決方案——Go Plugin。

          Go Plugin 提供了一種方式,通過(guò)在主程序和共享庫(kù)直接定義一系列的約定或者接口,就可以動(dòng)態(tài)加載其他人編譯的 Go 語(yǔ)言共享對(duì)象,使得主程序可以在編譯后動(dòng)態(tài)加載共享庫(kù),實(shí)現(xiàn)熱插拔的插件系統(tǒng)。此外主程序和共享庫(kù)的開發(fā)者不需要共享代碼,只要雙方的約定不變,修改共享庫(kù)后也不再需要重新編譯主程序。

          用戶只要根據(jù)規(guī)范要求,實(shí)現(xiàn)一段發(fā)壓業(yè)務(wù)邏輯代碼即可。Rhino 平臺(tái)可以自動(dòng)拉取代碼,觸發(fā)編譯。并將編譯后的插件 SO 文件分發(fā)到多個(gè)壓測(cè) Agent。 Agent 動(dòng)態(tài)加載 SO 文件,并發(fā)運(yùn)行起來(lái),就可以達(dá)到壓測(cè)的目的。此外,Rhino 還針對(duì)常見 Go Plugin 壓測(cè)場(chǎng)景,建立了壓測(cè)代碼示例代碼庫(kù)。對(duì)于壓測(cè)新手,簡(jiǎn)單修改下業(yè)務(wù)邏輯代碼,就可以完成壓測(cè)了。這樣就解決了非常見協(xié)議,以及復(fù)雜壓測(cè)場(chǎng)景等的壓測(cè)問(wèn)題。

          3.7 壓測(cè)引擎

          單 Agent 多引擎

          壓測(cè)調(diào)度的最小單元是壓測(cè) Agent,但是實(shí)際每個(gè) Agent 中有掛載多種壓測(cè)引擎的,來(lái)支撐不同的壓測(cè)場(chǎng)景。Rhino 平臺(tái)在壓測(cè)數(shù)據(jù)和壓測(cè)引擎之間增加了一個(gè)壓測(cè)引擎適配層,實(shí)現(xiàn)了壓測(cè)數(shù)據(jù)與壓測(cè)引擎的解耦。壓測(cè)引擎適配層,會(huì)根據(jù)選擇不同的壓測(cè)引擎,生成不同 Schema 的壓測(cè)數(shù)據(jù),啟用不同的引擎來(lái)完成壓測(cè),而這些對(duì)用戶是透明的。

          壓測(cè)引擎

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

          開源壓測(cè)引擎的優(yōu)點(diǎn)是維護(hù)人多,功能比較豐富,穩(wěn)定且性能好,缺點(diǎn)就是輸入格式固定,定制難度大。此外 Agent 與開源壓測(cè)引擎之間通常是不同進(jìn)程,進(jìn)程通信也存在比較大的問(wèn)題,不容易控制。

          自研壓測(cè)引擎,優(yōu)點(diǎn)是和 Agent 通常運(yùn)行在單進(jìn)程內(nèi),比較容易控制;缺點(diǎn)可能就是性能稍微差一些。但是 Golang 天然支持高并發(fā),因此自研和開源之間的性能差距并不明顯。

          • HTTP 協(xié)議:默認(rèn) Gatling ,單機(jī)發(fā)壓性能非常好,遠(yuǎn)超于 Jmeter。對(duì)于智能壓測(cè),或動(dòng)態(tài)調(diào)節(jié)的情況,會(huì)切換到自研壓測(cè)引擎上。
          • RPC 協(xié)議:自研引擎,主要利用 Golang 協(xié)程+RPC 連接池,來(lái)完成高并發(fā)壓測(cè)。
          • GoPlugin 協(xié)議:自研引擎,利用 Golang Plugin 可動(dòng)態(tài)裝載的特性,自動(dòng)裝載自定義壓測(cè)插件,來(lái)完成壓測(cè)。

          3.8 壓測(cè)監(jiān)控

          客戶端監(jiān)控

          由于公司監(jiān)控系統(tǒng),最小時(shí)間粒度是 30s,30s 內(nèi)的數(shù)據(jù)會(huì)聚合成一個(gè)點(diǎn)。這個(gè)時(shí)間粒度對(duì)于壓測(cè)來(lái)說(shuō)是比較難以接受的。因此,Rhino 平臺(tái)自己搭建了一套客戶端監(jiān)控系統(tǒng)。

          • 每個(gè) Request 都會(huì)以請(qǐng)求開始時(shí)間為基準(zhǔn)打一個(gè)點(diǎn)。
          • 單個(gè) Agent 內(nèi),會(huì)將相同任務(wù)相同接口,1s 內(nèi)的打點(diǎn)數(shù)據(jù)在本地做一次匯總,上報(bào)到 Kafka 中。
          • 監(jiān)控服務(wù)會(huì)消費(fèi) Kafka 中的打點(diǎn)數(shù)據(jù),將多個(gè) Agent 上報(bào)的數(shù)據(jù)進(jìn)行再次匯總,然后寫入數(shù)據(jù)庫(kù)中。
          • 前端監(jiān)控報(bào)表會(huì)實(shí)時(shí)拉取數(shù)據(jù)庫(kù)中監(jiān)控匯總數(shù)據(jù),繪制實(shí)時(shí)監(jiān)控曲線
          • 在監(jiān)控?cái)?shù)據(jù)匯總流程中,對(duì)于請(qǐng)求響應(yīng)時(shí)間的 PCT99 計(jì)算,是比較難處理的:目前 Rhino 平臺(tái)采用的 T-Digest 算法來(lái)計(jì)算 1 秒內(nèi)的 PCT99整個(gè)時(shí)間段內(nèi)的 PCT99 的計(jì)算,則是以 PCT & AGV 的方式聚合。即單位時(shí)間內(nèi)通過(guò) T-Digest 計(jì)算 PCT99;整個(gè)時(shí)間段內(nèi)的 PCT99,則是對(duì)所有點(diǎn)的 PCT99 取平均值。整體計(jì)算方案已與公司服務(wù)端監(jiān)控算法對(duì)齊,目的是減少客戶端監(jiān)控與服務(wù)端監(jiān)控之間的 Gap,減少壓測(cè)結(jié)果分析的干擾因素。

          服務(wù)端監(jiān)控

          服務(wù)端監(jiān)控,直接接入了公司 Metric 系統(tǒng)。

          • 在壓測(cè)過(guò)程中,Rhino 平臺(tái)會(huì)提供整條鏈路上所有節(jié)點(diǎn)核心指標(biāo)的監(jiān)控大盤,并高亮顯示可能存在風(fēng)險(xiǎn)的節(jié)點(diǎn),來(lái)提供實(shí)時(shí)預(yù)警。
          • 對(duì)于每個(gè)節(jié)點(diǎn)也都提供了實(shí)時(shí)的,詳細(xì)的監(jiān)控曲線圖。
          • 對(duì)于每個(gè)節(jié)點(diǎn)默認(rèn)提供 CPU、Memory、QPS 和 Error_Rate 等核心監(jiān)控指標(biāo),用戶可以在 Rhino 平臺(tái)上修改監(jiān)控配置,增加其他自定義監(jiān)控指標(biāo)。

          性能 Profile

          在壓測(cè)過(guò)程中,Rhino 平臺(tái)還可以實(shí)時(shí)采集目標(biāo)服務(wù)進(jìn)程的性能 Profile,并通過(guò)火焰圖的方式展示出來(lái),方便用戶進(jìn)行性能問(wèn)題分析和優(yōu)化,如圖。

          4. 壓測(cè)實(shí)踐

          Rhino 壓測(cè)平臺(tái)是一個(gè)面向全字節(jié)跳動(dòng)公司的,為了所有研發(fā)同學(xué)提供的一站式全鏈路壓測(cè)的平臺(tái)。Rhino 平臺(tái)的研發(fā)團(tuán)隊(duì),不僅負(fù)責(zé) Rhino 平臺(tái)的研發(fā)任務(wù),還會(huì)配合 QA&RD 來(lái)完成公司大型項(xiàng)目,重點(diǎn)業(yè)務(wù)的性能壓測(cè)工作。

          4.1 重大項(xiàng)目支撐

          公司內(nèi)重大項(xiàng)目的壓測(cè),Rhino 平臺(tái)都會(huì)積極參與,全力支撐的。其中,比較典型的項(xiàng)目有抖音春晚,西瓜百萬(wàn)英雄,春節(jié)紅包雨等活動(dòng)。

          其中字節(jié)春節(jié)紅包雨活動(dòng),完成是由 Rhino 團(tuán)隊(duì)來(lái)負(fù)責(zé)和完成的。字節(jié)春節(jié)紅包雨活動(dòng)是在春節(jié)期間,所有字節(jié)客戶端發(fā)起的,諸如抽卡分現(xiàn)金,紅包錦鯉,紅包雨等一系列的超大規(guī)模的紅包引流活動(dòng)。其流量規(guī)模巨大,流量突發(fā)性強(qiáng),業(yè)務(wù)邏輯和網(wǎng)絡(luò)架構(gòu)復(fù)雜度高等等,都對(duì) Rhino 平臺(tái)提出不小的挑戰(zhàn)。

          在春節(jié)紅包雨活動(dòng)中,所有用戶流量都經(jīng)過(guò)運(yùn)營(yíng)商專線接入到網(wǎng)絡(luò)邊緣的匯聚機(jī)房,然后經(jīng)過(guò)過(guò)濾和驗(yàn)證后,再轉(zhuǎn)發(fā)到核心機(jī)房。其中各個(gè) IDC 互為備份,其具體流量路線如圖。在這里,不僅要驗(yàn)證后端各服務(wù)是否能承載預(yù)期流程,還要驗(yàn)證各個(gè)專線帶寬,各個(gè)網(wǎng)關(guān)帶寬及轉(zhuǎn)發(fā)能力,各 IDC 承載能力以及之間帶寬等等。

          為此,我們將整個(gè)壓測(cè)拆分成多個(gè)階段,來(lái)簡(jiǎn)化壓測(cè)復(fù)雜性,也降低壓測(cè)問(wèn)題定位的難度:

          • 通過(guò)撥測(cè)/CDN 壓測(cè)來(lái)分別驗(yàn)證各個(gè)匯聚機(jī)房的承載能力,帶寬,以及網(wǎng)關(guān)性能。
          • 在各個(gè)匯聚機(jī)房部署壓測(cè) Agent,來(lái)模擬用戶流量分布,來(lái)壓測(cè)部署在核心機(jī)房的后端服務(wù)性能。
          • 單接口單實(shí)例壓測(cè),單接口單機(jī)房壓測(cè),場(chǎng)景化全鏈路單機(jī)房壓測(cè),場(chǎng)景化全鏈路全資源壓測(cè),分階段來(lái)驗(yàn)證后端服務(wù)性能。
          • 最后會(huì)通過(guò)全網(wǎng)撥測(cè),來(lái)模擬真實(shí)春節(jié)紅包雨高峰期流量,整體驗(yàn)證全系統(tǒng)性能。

          在這些大型項(xiàng)目的支撐中,Rhino 團(tuán)隊(duì)不僅學(xué)到了大量的業(yè)務(wù)和架構(gòu)設(shè)計(jì)知識(shí),還了解到業(yè)務(wù)研發(fā)同學(xué)如何看待壓測(cè),如何使用平臺(tái),幫助我們發(fā)現(xiàn)更多平臺(tái)的問(wèn)題,促進(jìn)平臺(tái)不斷迭代優(yōu)化。

          4.2 日常壓測(cè)任務(wù)支撐

          日常壓測(cè)支撐,也是 Rhino 平臺(tái)非常重要的一項(xiàng)任務(wù)。對(duì)于日常壓測(cè)中遇到的各種問(wèn)題,我們采用了各種方案來(lái)解決:

          • 專人 Oncall 值周,一對(duì)一指導(dǎo)。
          • 詳細(xì)完善的壓測(cè)知識(shí)庫(kù),不僅介紹了平臺(tái)如何使用,還包括壓測(cè)如何改造,壓測(cè)方案如何制定,壓測(cè)問(wèn)題如何定位。
          • 完善的性能培訓(xùn)體系:定期開展性能測(cè)試相關(guān)分享,并對(duì)于 QA&RD 團(tuán)隊(duì),也會(huì)開展專業(yè)的壓測(cè)培訓(xùn)。

          4.3 線上流量調(diào)度

          Rhino 平臺(tái)還實(shí)現(xiàn)了線上流量的定期調(diào)度,以達(dá)到線上實(shí)例自動(dòng)壓測(cè)的目的[8]:

          • 將線上流量逐步調(diào)度到目標(biāo)實(shí)例上,來(lái)測(cè)試服務(wù)實(shí)例性能極限,并給出實(shí)例性能 Profile,分析出實(shí)例性能瓶頸。
          • 通過(guò)長(zhǎng)期的流量調(diào)度,來(lái)觀察服務(wù)實(shí)例性能變化,以監(jiān)控服務(wù)性能的變化趨勢(shì)。
          • 通過(guò)不同資源水位下的實(shí)例性能,來(lái)預(yù)估出整個(gè)集群容量。完成對(duì)服務(wù)容量預(yù)估,以及線上風(fēng)險(xiǎn)評(píng)估。
          • 基于泳道化的流量調(diào)度,可以精確的預(yù)估服務(wù)集群容量。

          其具體實(shí)現(xiàn)方案如下:

          • 修改負(fù)載均衡中目標(biāo)實(shí)例的權(quán)重 Weight 值,逐步調(diào)大該 Weight 值,將更多流量集中打到目標(biāo)實(shí)例,直到達(dá)到設(shè)置的停止閾值。

          目前已經(jīng)有 500+微服務(wù)接入,每天定時(shí)執(zhí)行流量調(diào)度,來(lái)監(jiān)控線上服務(wù)性能變化趨勢(shì),如下圖。

          4.4 常態(tài)化壓測(cè)

          Rhino 平臺(tái)目前還在公司內(nèi)推行常態(tài)化壓測(cè),通過(guò)周期定時(shí)化的自動(dòng)化全鏈路壓測(cè),來(lái)實(shí)現(xiàn)以下目標(biāo):

          • 實(shí)時(shí)監(jiān)控線上服務(wù)集群容量,防止服務(wù)性能劣化。
          • 實(shí)時(shí)監(jiān)控線上鏈路容量,防止鏈路性能劣化。

          目前 Rhino 平臺(tái)上的常態(tài)化壓測(cè),會(huì)周期定時(shí),以無(wú)人值守的方式,自動(dòng)執(zhí)行壓測(cè)任務(wù),并推送壓測(cè)結(jié)果。在壓測(cè)執(zhí)行過(guò)程中,會(huì)根據(jù)調(diào)用鏈自動(dòng)完成壓測(cè)開關(guān)開啟,發(fā)起壓測(cè)流量。實(shí)時(shí)監(jiān)控服務(wù)性能指標(biāo),并根據(jù) Metric 及告警監(jiān)控,自動(dòng)完成壓測(cè)熔斷,以保證壓測(cè)安全。

          目前已經(jīng)有多個(gè)業(yè)務(wù)方接入常態(tài)化壓測(cè),以此保證線上服務(wù)的穩(wěn)定性。

          4.5 DevOps 流水線中的壓測(cè)

          服務(wù)在上線時(shí),都會(huì)經(jīng)過(guò)預(yù)發(fā)布,線上小流量灰度,線上全量發(fā)布。在這個(gè)過(guò)程中,我們可以通過(guò)線上測(cè)試 Case 以及灰度發(fā)布,來(lái)攔截服務(wù)線上功能缺陷。但是對(duì)于性能缺陷的攔截,卻不夠有效。

          從線上故障跟蹤系統(tǒng)里就可以發(fā)現(xiàn),由于上線前沒(méi)有做好性能壓測(cè),很多性能缺陷都逃逸到了線上。

          為了攔截各種性能缺陷,Rhino 平臺(tái)完成了 DevOps 平臺(tái)的打通。將壓測(cè)服務(wù)在 DevOps 平臺(tái)上注冊(cè)成一個(gè)原子服務(wù) ,研發(fā)人員可以將壓測(cè)節(jié)點(diǎn)編排在任意流水線的任意位置,實(shí)現(xiàn)上線前的例行壓測(cè)。DevOps 流水線中的壓測(cè),不僅可以幫助 RD 發(fā)現(xiàn)代碼中的性能問(wèn)題,還能與性能基線進(jìn)行 Diff,來(lái)發(fā)現(xiàn)代碼性能變壞的味道。

          5. 總結(jié)與展望

          5.1 總結(jié)

          Rhino 壓測(cè)平臺(tái)從立項(xiàng)到現(xiàn)在,不到兩年的時(shí)間內(nèi),其發(fā)展已經(jīng)初具規(guī)模,如圖(每月壓測(cè)執(zhí)行統(tǒng)計(jì))。這個(gè)期間,非常非常感謝公司內(nèi)所有合作團(tuán)隊(duì),尤其是架構(gòu)團(tuán)隊(duì),中臺(tái)團(tuán)隊(duì)對(duì)壓測(cè)平臺(tái)的支撐,沒(méi)有他們的支撐,全鏈路壓測(cè)建設(shè)是難以完成的。

          5.2 未來(lái)發(fā)展

          業(yè)務(wù)深層次定制化

          通用壓測(cè)平臺(tái)已經(jīng)初步搭建完成,基本上能滿足業(yè)務(wù)線日常壓測(cè)需求。但在日常壓測(cè)支撐過(guò)程中,發(fā)現(xiàn)不同業(yè)務(wù)線在壓測(cè)時(shí),但是仍然有大量的前置和后繼工作需要人工來(lái)完成。

          如何更進(jìn)一步降低業(yè)務(wù)方壓測(cè)改造的成本,如何減少壓測(cè)環(huán)境數(shù)據(jù)預(yù)置成本,如何快速完成壓測(cè)數(shù)據(jù)清理,如何快速定位出性能問(wèn)題等等,Rhino 壓測(cè)平臺(tái)后續(xù)將更進(jìn)一步深入業(yè)務(wù),與各大業(yè)務(wù)方開展更深入的合作,提供更深度的業(yè)務(wù)定制,為研發(fā)提效,助力業(yè)務(wù)線發(fā)展。

          壓測(cè)與容量規(guī)劃

          業(yè)務(wù)目前資源是否充足,其具體容量是多少;按照目前業(yè)務(wù)增長(zhǎng),其機(jī)器資源還能支撐多久?

          目前服務(wù)資源利用如何,是否可以優(yōu)化,如何更進(jìn)一步提升資源利用率,降低機(jī)器資源成本?

          某大型活動(dòng),需要申請(qǐng)多少資源?是否不需要壓測(cè),或者自動(dòng)化利用線上流量數(shù)據(jù),或者利用日常壓測(cè)數(shù)據(jù),就可以給出上述問(wèn)題的結(jié)論?

          壓測(cè)與 SRE

          如何保證服務(wù)穩(wěn)定性,如何監(jiān)控服務(wù)性能劣化并及時(shí)預(yù)警,限流、超時(shí)、重試以及熔斷等服務(wù)治理措施配置是否合理?以及如何配合混沌測(cè)試進(jìn)行容災(zāi)演練,保證服務(wù)穩(wěn)定性等等,這些 Rhino 平臺(tái)都會(huì)做更進(jìn)一步探索。

          6. 招聘

          目前 Rhino 團(tuán)隊(duì)還非常小,非常缺少性能測(cè)試以及后端開發(fā)相關(guān)的研發(fā)工程師,歡迎感興趣的同學(xué)來(lái)加入。簡(jiǎn)歷投遞郵箱: tech@bytedance.com ;郵件標(biāo)題: 姓名 - 工作年限 - Rhino 。

          參考文獻(xiàn)

          [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:行進(jìn)中的智能 Monkey

          品質(zhì)優(yōu)化 - 圖文詳情頁(yè)秒開實(shí)踐

          Android Camera 內(nèi)存問(wèn)題剖析

          字節(jié)跳動(dòng)自研線上引流回放系統(tǒng)的架構(gòu)演進(jìn)


          歡迎關(guān)注「字節(jié)跳動(dòng)技術(shù)團(tuán)隊(duì)」

          得不佩服,美觀小巧的網(wǎng)頁(yè)內(nèi)容編輯器——ContentTools


          愛(ài)分享Coder

          2019-12-03 · 軟件開發(fā)工程師 優(yōu)質(zhì)科技領(lǐng)域創(chuàng)作者

          介紹

          ContentTools是一個(gè)美觀小巧的網(wǎng)頁(yè)內(nèi)容工具(一個(gè)JS庫(kù)),具備所見即所得(WYSIWYG)的編輯器功能,只需幾個(gè)簡(jiǎn)單的步驟,即可將ContentTools添加到任何HTML頁(yè)面。如下圖所示頁(yè)面通過(guò)實(shí)時(shí)ContentTool的彈出層實(shí)現(xiàn)實(shí)時(shí)編輯功能。用小而美來(lái)形容它最好不過(guò)了!

          Github地址

          https://github.com/GetmeUK

          特性

          ContentTools是用于HTML頁(yè)面的美觀小巧的內(nèi)容編輯器。它被設(shè)計(jì)為:

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

          功能簡(jiǎn)介

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

          1、加粗顯示

          2、斜體顯示

          3、超鏈接

          4、H標(biāo)題

          5、正文

          6、有序和無(wú)序列表

          7、插入表格

          8、插入圖片

          9、視頻

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

          使用

          • 第一步是下載JS,CSS和其他關(guān)聯(lián)的項(xiàng)目文件:

          下載倉(cāng)庫(kù)并打開/ build文件夾,包括預(yù)構(gòu)建的源文件。將文件夾的內(nèi)容復(fù)制到項(xiàng)目的適當(dāng)位置(例如,content-tools.min.js>

          /www/scripts/content-tools.min.js)。但是,/ images文件夾和icons.woff字體需要復(fù)制到與content-tools.min.css相同的文件夾中,文件結(jié)構(gòu)應(yīng)類似于:

          • 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>

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

          <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屬性用于在保存時(shí)標(biāo)識(shí)區(qū)域(默認(rèn)情況下使用id屬性),標(biāo)記可編輯HTML時(shí),常見的誤解是將單個(gè)元素標(biāo)記為可編輯,例如:

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

          正確的使用方式如下,也就是說(shuō)必須要在特定的容器元素內(nèi)

          <div data-editable data-name=heading>

          <h1>Content</h1>

          </div>

          • 準(zhǔn)備CSS

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

          [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%;

          }

          /* 左對(duì)齊 */

          [data-editable] .align-left {

          clear: initial;

          float: left;

          margin-right: 0.5em;

          }

          /* 右對(duì)齊 */

          [data-editable].align-right {

          clear: initial;

          float: right;

          margin-left: 0.5em;

          }

          /* 可編輯區(qū)域中文本的對(duì)齊樣式 */

          [data-editable] .text-center {

          text-align: center;

          }

          [data-editable] .text-left {

          text-align: left;

          }

          [data-editable] .text-right {

          text-align: right;

          }

          • 初始化編輯器

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

          1. 我們希望用戶能夠?qū)SS樣式應(yīng)用于元素。
          2. 我們希望頁(yè)面的區(qū)域是可編輯的。
          3. 一種保存我們的內(nèi)容的機(jī)制。
          4. 我們可能還會(huì)配置圖像處理程序等等

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

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

          var editor;

          });

          • 配置樣式

          就像文字處理程序一樣,可以為內(nèi)容配置一系列預(yù)定義樣式。當(dāng)用戶從視口底部的檢查器欄中選擇標(biāo)簽時(shí),這些標(biāo)簽就會(huì)出現(xiàn)。盡管可以將樣式設(shè)置為適用于所有標(biāo)簽,但是僅顯示適用于標(biāo)簽類型的樣式。

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

          ContentTools.StylePalette.add([

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

          ]);

          StylePalette.add方法使我們可以向編輯器添加樣式列表。每種樣式均聲明為一個(gè)Style實(shí)例,該實(shí)例使用顯示名稱,CSS類和可以應(yīng)用該樣式的標(biāo)簽列表初始化。我們需要添加相關(guān)的CSS來(lái)支持這種樣式,因此在HTML的開頭添加:

          <head>

          ...

          <style>

          .author {

          font-style: italic;

          font-weight: bold;

          }

          </style>

          </head>

          • 選擇可編輯區(qū)域

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

          editor=ContentTools.EditorApp.get();

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

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

          • 保存更改

          最后,我們希望在用戶保存頁(yè)面時(shí)得到通知,以便我們可以將每個(gè)區(qū)域的更新內(nèi)容存儲(chǔ)在文件或數(shù)據(jù)庫(kù)中。為此,我們監(jiān)聽由編輯器觸發(fā)的保存事件。在editor.init語(yǔ)句之后,將以下代碼添加到editor.js中:

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

          var name, payload, regions, xhr;

          // 檢查是否已更改

          regions=ev.detail().regions;

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

          return;

          }

          // 保存更改時(shí)將編輯器設(shè)置為忙

          this.busy(true);

          // 將每個(gè)區(qū)域的內(nèi)容收集到一個(gè)FormData實(shí)例中

          payload=new FormData();

          for (name in regions) {

          if (regions.hasOwnProperty(name)) {

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

          }

          }

          // 將更新內(nèi)容發(fā)送到要保存的服務(wù)器

          function onStateChange(ev) {

          // 檢查請(qǐng)求是否完成

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

          editor.busy(false);

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

          // 保存成功,通知前臺(tái)

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

          } else {

          // 保存失敗,通知前臺(tái)

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

          }

          }

          };

          xhr=new XMLHttpRequest();

          xhr.addEventListener('readystatechange', onStateChange);

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

          xhr.send(payload);

          });

          當(dāng)用戶保存頁(yè)面時(shí),我們可以使用AJAX將每個(gè)區(qū)域的內(nèi)容發(fā)送到服務(wù)器進(jìn)行保存。在瀏覽器中打開頁(yè)面,尋找左上方的藍(lán)色編輯按鈕,然后單擊它以開始編輯。





          總結(jié)

          這樣一個(gè)美觀且強(qiáng)大的即時(shí)編輯器可謂是非常的實(shí)用,特別是對(duì)于一些內(nèi)容編輯網(wǎng)站,如CMS、靜態(tài)文檔網(wǎng)站、博客等內(nèi)容型網(wǎng)站尤其有用,希望對(duì)你有所幫助,Enjoy it!

          1.5萬(wàn)閱讀

          搜索

          專門制作文字特效軟件

          網(wǎng)站制作微信小程序

          html5編輯軟件排行榜

          傻瓜式網(wǎng)頁(yè)制作軟件

          網(wǎng)站制作軟件免費(fèi)版

          一鍵網(wǎng)站制作app

          實(shí)現(xiàn)css兩端對(duì)齊,我在網(wǎng)上找了很多方法,都不怎么實(shí)用,都是兼容性鬧得,column是css3的屬性,是多列布局,使用column來(lái)實(shí)現(xiàn)兩端對(duì)齊簡(jiǎn)單實(shí)用,就要設(shè)置下模塊的個(gè)數(shù)跟column的列數(shù)一致就行,先看它的的3個(gè)屬性:

          1.column-count 屬性規(guī)定元素應(yīng)該被分隔的列數(shù)

          2.column-gap 屬性規(guī)定列之間的間隔

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

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

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

          <!Doctype html>

          <html>

          <head>

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

          <title>實(shí)現(xiàn)css兩端對(duì)齊</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>

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

          除注明外的文章,均為來(lái)源:湯久生博客,轉(zhuǎn)載請(qǐng)保留本文地址!

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


          主站蜘蛛池模板: 亚洲国产精品一区| 色多多免费视频观看区一区| 亚洲中文字幕无码一区二区三区 | 中文字幕一区视频| 少妇无码AV无码一区| 色一情一乱一伦一区二区三区 | 免费av一区二区三区| 亚洲国产精品综合一区在线 | 免费播放一区二区三区| 久久国产午夜精品一区二区三区| 中文字幕日韩人妻不卡一区| www一区二区三区| 久久一区二区明星换脸| 国产色综合一区二区三区 | 一区二区三区亚洲视频| 日韩毛片一区视频免费| 精品黑人一区二区三区| 精品一区二区三区免费毛片爱| 国产成人无码精品一区二区三区 | 99热门精品一区二区三区无码 | 日本不卡一区二区视频a| 无码中文字幕一区二区三区| 婷婷国产成人精品一区二 | 日韩精品无码一区二区三区免费| 精品一区二区三区无码免费视频| 国产成人精品无码一区二区三区 | 亚洲一区精彩视频| 精品国产毛片一区二区无码| 另类ts人妖一区二区三区| 亚洲一区二区三区无码国产| 蜜桃视频一区二区三区在线观看| 欧美成人aaa片一区国产精品| 日本精品高清一区二区2021| 亚洲精品国产suv一区88| 国精产品一区一区三区| 日韩精品无码免费一区二区三区| 日本内射精品一区二区视频 | 亚洲国产综合无码一区| 亚洲乱码一区二区三区在线观看| 无码人妻一区二区三区在线水卜樱 | 国产福利电影一区二区三区|