隨著公司業(yè)務(wù)的不斷擴張,用戶流量在不斷提升,研發(fā)體系的規(guī)模和復雜性也隨之增加。線上服務(wù)的穩(wěn)定性也越來越重要,服務(wù)性能問題,以及容量問題也越發(fā)明顯。
因此有必要搭建一個有效壓測系統(tǒng),提供安全、高效、真實的線上全鏈路壓測服務(wù),為線上服務(wù)保駕護航。
關(guān)于全鏈路壓測的建設(shè),業(yè)界已經(jīng)有了非常多文章,但是涉及到具體的技術(shù)實現(xiàn)方面,卻很少介紹。本文想從全鏈路壓測系統(tǒng),從設(shè)計到落地整個實踐過程,來詳細介紹下全鏈路壓測系統(tǒng)是具體是如何設(shè)計,以及如何落地的。希望能從技術(shù)落地實踐的角度,給同行業(yè)的同學一些參考和啟發(fā)。
全鏈路壓測在業(yè)內(nèi)已經(jīng)有了廣泛的實踐,如阿里的 Amazon、PTS[1][2],美團的 Quake[3][4],京東的的 ForceBOT[5],高德的 TestPG[6]等等,都為我們提供豐富的實踐經(jīng)驗,和大量優(yōu)秀的技術(shù)方案。我們廣泛吸收了各大互聯(lián)網(wǎng)公司的全鏈路壓測建設(shè)經(jīng)驗,并基于字節(jié)跳動業(yè)務(wù)需求,設(shè)計開發(fā)了一個全鏈路壓測系統(tǒng) Rhino。
Rhino 平臺作為公司級的全鏈路壓測平臺,它的目標是對全公司所有業(yè)務(wù),提供單服務(wù)、全鏈路,安全可靠、真實、高效的壓測,來幫助業(yè)務(wù)高效便捷的完成性能測試任務(wù),更精確評估線上服務(wù)性能&容量方面風險。
因此在 Rhino 平臺設(shè)計之初,我們就定下以下目標:
Rhino 是一個分布式全鏈路壓測系統(tǒng),可以通過水平擴展,來實現(xiàn)模擬海量用戶真實的業(yè)務(wù)操作場景,對線上各種業(yè)務(wù)進行全方位的性能測試。它主要分為控制中心(Rhino Master)模塊,壓測鏈路服務(wù)模塊,監(jiān)控系統(tǒng)模塊,壓測引擎模塊,如圖。(每一個模塊都是由多個微服務(wù)來完成的。如下圖每個實線圖都代表一個微服務(wù)或多個微服務(wù))。
壓測過程中數(shù)據(jù)構(gòu)造是最重要,也是最為復雜的環(huán)節(jié)。壓測數(shù)據(jù)的建模,直接影響了壓測結(jié)果的準確性。
為了高效的構(gòu)造特定的 Fake 壓測數(shù)據(jù),Rhino 壓測平臺提供大量數(shù)據(jù)構(gòu)造方式:
在壓測過程中,有些壓測請求需要進行登錄,并保持會話;此外在很多壓測請求中涉及到用戶賬號信息 UserID,DeviceID 等數(shù)據(jù)。用戶賬號的構(gòu)造問題,一直是壓測過程中非常棘手的問題。Rhino 平臺打通的用戶中心,設(shè)置了壓測專屬的賬號服務(wù),完美地解決了壓測過程中的登錄態(tài),以及測試賬號等問題。具體流程和使用界面,如下圖。
壓測隔離中需要解決的壓測流量隔離,以及壓測數(shù)據(jù)的隔離。
壓測流量隔離,主要是通過構(gòu)建壓測環(huán)境來解決,如線下壓測環(huán)境,或泳道化/Set 化建設(shè),將壓測流量與線上流程完全隔離。優(yōu)點是壓測流量與線上流量完全隔離,不會影響到線上用戶。缺點:機器資源及維護成本高,且壓測結(jié)果需要經(jīng)過一定的換算,才能得線上容量,結(jié)果準確性存在一定的問題。目前公司內(nèi)壓測都是在線上集群上完成的,線上泳道化正在建設(shè)中。
壓測數(shù)據(jù)隔離,主要是通過對壓測流量進行染色,讓線上服務(wù)能識別哪些是壓測流量,哪些是正常流量,然后對壓測流量進行特殊處理,以達到數(shù)據(jù)隔離的目的。目前 Rhino 平臺整體壓測隔離框架如圖。
壓測標記就是最常見的壓測流量染色的方式。
目前公司內(nèi)各個基礎(chǔ)組件、存儲組件,以及 RPC 框架都已經(jīng)支持了壓測標記的透傳。其原理是將壓測標記的 KV 值存入 Context 中,然后在所有下游請求中都帶上該 Context,下游服務(wù)可以根據(jù) Context 中壓測標記完成對壓測流量的處理。在實際業(yè)務(wù)中,代碼改造也非常簡單,只需要透傳 Context 即可。
Golang 服務(wù): 將壓測標記寫入 Context 中。
Python 服務(wù):利用 threading.local()存儲線程 Context。
Java 服務(wù):利用 ThreadLocal 存儲線程 Context。
為了解決線上壓測安全問題,我們還引入了壓測開關(guān)組件。
線上壓測中,最復雜的問題就是壓測鏈路中涉及到寫操作,如何避免污染線上數(shù)據(jù),并且能保證壓測請求保持和線上相同的請求路徑。業(yè)界有很多解決方案,常見的有影子表,影子庫,以及數(shù)據(jù)偏移,如圖[7]。
Rhino 平臺針對不同存儲,有不同的解決方案:
在壓測之前,需要對服務(wù)進行壓測驗證。對于不滿足壓測要求(即壓測數(shù)據(jù)隔離)的服務(wù),需要進行壓測改造。
a. 盡量減少代碼改動,并給出完整的指導手冊及代碼示例,減少 RD 的工作量,降低代碼錯誤的可能性
b. 提供簡單便捷的線上線下 HTTP&RPC 的壓測請求 Debug 工具,方便代碼改動的驗證
c. 對于新項目,在項目開始初期,就將壓測改造加入項目開發(fā)規(guī)范中,減少后期的代碼改動
請求調(diào)用鏈,對于線上壓測是非常重要的:
Rhino 平臺通過公司的流式日志系統(tǒng)來完成調(diào)用鏈檢索的。一個服務(wù)在被請求或者請求下游時,都會透傳一個 LogID。RPC 框架會打印調(diào)用鏈日志(包括 RPC 日志-調(diào)用者日志,Access 日志-被調(diào)用者日志),所有日志中都會包含這個 LogID。通過 LogID 將一個請求所經(jīng)過的所有服務(wù)日志串起來,就完成調(diào)用鏈檢索。
Rhino 平臺在公司流式日志系統(tǒng)提供的鏈路梳理功能基礎(chǔ)上,進行了進一步優(yōu)化,以滿足壓測需要:
雖然 Rhino 平臺對于壓測有很多的安全保障措施,但是對于大型壓測,保證信息的通暢流通也是非常重要的。因此在壓測周知方面,Rhino 平臺也提供了很多解決方案:
在壓測之前,需要開啟整體鏈路的壓測開關(guān)的,否則壓測流量就會被服務(wù)拒絕,導致壓測失敗。
對于調(diào)用鏈中不能壓測的服務(wù)(敏感服務(wù)),或者第三方服務(wù),為了壓測請求的完整性,就需要對這些服務(wù)進行 Mock。業(yè)界通用的 Mock 方案有:
由于字節(jié)整個公司都采用微服務(wù)架構(gòu),導致一次壓測涉及鏈路都比較長,快速無業(yè)務(wù)入侵的 Mock
方式成為了首選。Rhino 平臺是通過公司 Service Mesh 和 ByteMock 系統(tǒng)來實現(xiàn)了高效的,對業(yè)務(wù)透明的服務(wù) Mock。
壓測執(zhí)行前,Rhino 平臺需要向 Service Mesh 注冊染色轉(zhuǎn)發(fā)規(guī)則,并向 Mock 服務(wù)注冊 Mock 規(guī)則。然后在壓測流量中注入 Mock 染色標記,才能完成服務(wù) Mock:
Rhino 平臺中,壓測 Agent 就是一個最小調(diào)度單元。一次壓測任務(wù),通常會拆分成多個子 Job,然后下發(fā)到多個 Agent 上來完成。
2020 年春節(jié)搶紅包壓測中,Rhino 臨時擴容在 4000+個實例,支撐了單次 3kw+QPS 的壓測,但日常 Rhino 平臺只部署了 100+個實例,就能滿足日常壓測需求。
Rhino 平臺默認將全鏈路壓測分為公網(wǎng)壓測和內(nèi)網(wǎng)壓測。公網(wǎng)壓測主要 IDC 網(wǎng)絡(luò)帶寬,延時,IDC 網(wǎng)關(guān)新建連接、轉(zhuǎn)發(fā)等能力;內(nèi)網(wǎng)壓測,主要是壓測目標服務(wù),目標集群的 性能,容量等。
Rhino 平臺在各個 IDC 都有部署 Agent 集群。各個 IDC 內(nèi)服務(wù)的壓測,默認會就近選擇壓測 Agent,來減少網(wǎng)絡(luò)延時對壓測結(jié)果的干擾,使得壓測結(jié)果更精準,壓測問題定位更簡單。
除了多機房部署之外,Rhino 平臺還在邊緣計算節(jié)點上也部署了壓測 Agent,來模擬各種不同地域不同運營商的流量請求,確保流量來源,流量分布更貼近真實情況。在 Rhino 平臺上可以選擇不同地域不同運營商,從全國各個地區(qū)發(fā)起壓測流量。
為了應(yīng)對線上壓測風險,Rhino 平臺提供兩種熔斷方式,來應(yīng)對壓測過程中的突發(fā)事件,來降低對線上服務(wù)造成的影響。
每個壓測任務(wù),都可以關(guān)聯(lián)調(diào)用鏈中任意服務(wù)的告警規(guī)則。在壓測任務(wù)執(zhí)行過程,Rhino 平臺會主動監(jiān)聽告警服務(wù)。 當調(diào)用鏈中有服務(wù)出現(xiàn)了告警,會立即停止壓測。對于沒有關(guān)聯(lián)的告警,Rhino 平臺也會記錄下來,便于壓測問題定位。
自定義監(jiān)控指標及閾值,到達閾值后,也會自動停止壓測。目前支持 CPU、Memory、 上游穩(wěn)定性、錯誤日志,以及其他自定義指標。
此外,除了 Rhino 平臺自身提供的熔斷機制以外,公司服務(wù)治理架構(gòu)也提供了很多額外的熔斷機制,如壓測開關(guān),一鍵切斷壓測流量;過載保護,服務(wù)過載時自動丟棄壓測流量。
對于 HTTP 協(xié)議,參考了 Postman,全部可視化操作,保證所有人都能上手操作,極大降低了壓測的使用門檻和成本。
對于 RPC 任務(wù),Rhino 也自動完成了對 IDL 的解析,然后轉(zhuǎn)換成 JSON 格式,便于用戶參數(shù)化處理。
對于非 HTTP/RPC 的協(xié)議,以及有復雜邏輯的壓測任務(wù),Rhino 平臺也提供了完善的解決方案——Go Plugin。
Go Plugin 提供了一種方式,通過在主程序和共享庫直接定義一系列的約定或者接口,就可以動態(tài)加載其他人編譯的 Go 語言共享對象,使得主程序可以在編譯后動態(tài)加載共享庫,實現(xiàn)熱插拔的插件系統(tǒng)。此外主程序和共享庫的開發(fā)者不需要共享代碼,只要雙方的約定不變,修改共享庫后也不再需要重新編譯主程序。
用戶只要根據(jù)規(guī)范要求,實現(xiàn)一段發(fā)壓業(yè)務(wù)邏輯代碼即可。Rhino 平臺可以自動拉取代碼,觸發(fā)編譯。并將編譯后的插件 SO 文件分發(fā)到多個壓測 Agent。 Agent 動態(tài)加載 SO 文件,并發(fā)運行起來,就可以達到壓測的目的。此外,Rhino 還針對常見 Go Plugin 壓測場景,建立了壓測代碼示例代碼庫。對于壓測新手,簡單修改下業(yè)務(wù)邏輯代碼,就可以完成壓測了。這樣就解決了非常見協(xié)議,以及復雜壓測場景等的壓測問題。
壓測調(diào)度的最小單元是壓測 Agent,但是實際每個 Agent 中有掛載多種壓測引擎的,來支撐不同的壓測場景。Rhino 平臺在壓測數(shù)據(jù)和壓測引擎之間增加了一個壓測引擎適配層,實現(xiàn)了壓測數(shù)據(jù)與壓測引擎的解耦。壓測引擎適配層,會根據(jù)選擇不同的壓測引擎,生成不同 Schema 的壓測數(shù)據(jù),啟用不同的引擎來完成壓測,而這些對用戶是透明的。
在壓測引擎上,我們有開源的壓測引擎,也有自研的壓測引擎。
開源壓測引擎的優(yōu)點是維護人多,功能比較豐富,穩(wěn)定且性能好,缺點就是輸入格式固定,定制難度大。此外 Agent 與開源壓測引擎之間通常是不同進程,進程通信也存在比較大的問題,不容易控制。
自研壓測引擎,優(yōu)點是和 Agent 通常運行在單進程內(nèi),比較容易控制;缺點可能就是性能稍微差一些。但是 Golang 天然支持高并發(fā),因此自研和開源之間的性能差距并不明顯。
由于公司監(jiān)控系統(tǒng),最小時間粒度是 30s,30s 內(nèi)的數(shù)據(jù)會聚合成一個點。這個時間粒度對于壓測來說是比較難以接受的。因此,Rhino 平臺自己搭建了一套客戶端監(jiān)控系統(tǒng)。
服務(wù)端監(jiān)控,直接接入了公司 Metric 系統(tǒng)。
在壓測過程中,Rhino 平臺還可以實時采集目標服務(wù)進程的性能 Profile,并通過火焰圖的方式展示出來,方便用戶進行性能問題分析和優(yōu)化,如圖。
Rhino 壓測平臺是一個面向全字節(jié)跳動公司的,為了所有研發(fā)同學提供的一站式全鏈路壓測的平臺。Rhino 平臺的研發(fā)團隊,不僅負責 Rhino 平臺的研發(fā)任務(wù),還會配合 QA&RD 來完成公司大型項目,重點業(yè)務(wù)的性能壓測工作。
公司內(nèi)重大項目的壓測,Rhino 平臺都會積極參與,全力支撐的。其中,比較典型的項目有抖音春晚,西瓜百萬英雄,春節(jié)紅包雨等活動。
其中字節(jié)春節(jié)紅包雨活動,完成是由 Rhino 團隊來負責和完成的。字節(jié)春節(jié)紅包雨活動是在春節(jié)期間,所有字節(jié)客戶端發(fā)起的,諸如抽卡分現(xiàn)金,紅包錦鯉,紅包雨等一系列的超大規(guī)模的紅包引流活動。其流量規(guī)模巨大,流量突發(fā)性強,業(yè)務(wù)邏輯和網(wǎng)絡(luò)架構(gòu)復雜度高等等,都對 Rhino 平臺提出不小的挑戰(zhàn)。
在春節(jié)紅包雨活動中,所有用戶流量都經(jīng)過運營商專線接入到網(wǎng)絡(luò)邊緣的匯聚機房,然后經(jīng)過過濾和驗證后,再轉(zhuǎn)發(fā)到核心機房。其中各個 IDC 互為備份,其具體流量路線如圖。在這里,不僅要驗證后端各服務(wù)是否能承載預期流程,還要驗證各個專線帶寬,各個網(wǎng)關(guān)帶寬及轉(zhuǎn)發(fā)能力,各 IDC 承載能力以及之間帶寬等等。
為此,我們將整個壓測拆分成多個階段,來簡化壓測復雜性,也降低壓測問題定位的難度:
在這些大型項目的支撐中,Rhino 團隊不僅學到了大量的業(yè)務(wù)和架構(gòu)設(shè)計知識,還了解到業(yè)務(wù)研發(fā)同學如何看待壓測,如何使用平臺,幫助我們發(fā)現(xiàn)更多平臺的問題,促進平臺不斷迭代優(yōu)化。
日常壓測支撐,也是 Rhino 平臺非常重要的一項任務(wù)。對于日常壓測中遇到的各種問題,我們采用了各種方案來解決:
Rhino 平臺還實現(xiàn)了線上流量的定期調(diào)度,以達到線上實例自動壓測的目的[8]:
其具體實現(xiàn)方案如下:
目前已經(jīng)有 500+微服務(wù)接入,每天定時執(zhí)行流量調(diào)度,來監(jiān)控線上服務(wù)性能變化趨勢,如下圖。
Rhino 平臺目前還在公司內(nèi)推行常態(tài)化壓測,通過周期定時化的自動化全鏈路壓測,來實現(xiàn)以下目標:
目前 Rhino 平臺上的常態(tài)化壓測,會周期定時,以無人值守的方式,自動執(zhí)行壓測任務(wù),并推送壓測結(jié)果。在壓測執(zhí)行過程中,會根據(jù)調(diào)用鏈自動完成壓測開關(guān)開啟,發(fā)起壓測流量。實時監(jiān)控服務(wù)性能指標,并根據(jù) Metric 及告警監(jiān)控,自動完成壓測熔斷,以保證壓測安全。
目前已經(jīng)有多個業(yè)務(wù)方接入常態(tài)化壓測,以此保證線上服務(wù)的穩(wěn)定性。
服務(wù)在上線時,都會經(jīng)過預發(fā)布,線上小流量灰度,線上全量發(fā)布。在這個過程中,我們可以通過線上測試 Case 以及灰度發(fā)布,來攔截服務(wù)線上功能缺陷。但是對于性能缺陷的攔截,卻不夠有效。
從線上故障跟蹤系統(tǒng)里就可以發(fā)現(xiàn),由于上線前沒有做好性能壓測,很多性能缺陷都逃逸到了線上。
為了攔截各種性能缺陷,Rhino 平臺完成了 DevOps 平臺的打通。將壓測服務(wù)在 DevOps 平臺上注冊成一個原子服務(wù) ,研發(fā)人員可以將壓測節(jié)點編排在任意流水線的任意位置,實現(xiàn)上線前的例行壓測。DevOps 流水線中的壓測,不僅可以幫助 RD 發(fā)現(xiàn)代碼中的性能問題,還能與性能基線進行 Diff,來發(fā)現(xiàn)代碼性能變壞的味道。
Rhino 壓測平臺從立項到現(xiàn)在,不到兩年的時間內(nèi),其發(fā)展已經(jīng)初具規(guī)模,如圖(每月壓測執(zhí)行統(tǒng)計)。這個期間,非常非常感謝公司內(nèi)所有合作團隊,尤其是架構(gòu)團隊,中臺團隊對壓測平臺的支撐,沒有他們的支撐,全鏈路壓測建設(shè)是難以完成的。
通用壓測平臺已經(jīng)初步搭建完成,基本上能滿足業(yè)務(wù)線日常壓測需求。但在日常壓測支撐過程中,發(fā)現(xiàn)不同業(yè)務(wù)線在壓測時,但是仍然有大量的前置和后繼工作需要人工來完成。
如何更進一步降低業(yè)務(wù)方壓測改造的成本,如何減少壓測環(huán)境數(shù)據(jù)預置成本,如何快速完成壓測數(shù)據(jù)清理,如何快速定位出性能問題等等,Rhino 壓測平臺后續(xù)將更進一步深入業(yè)務(wù),與各大業(yè)務(wù)方開展更深入的合作,提供更深度的業(yè)務(wù)定制,為研發(fā)提效,助力業(yè)務(wù)線發(fā)展。
業(yè)務(wù)目前資源是否充足,其具體容量是多少;按照目前業(yè)務(wù)增長,其機器資源還能支撐多久?
目前服務(wù)資源利用如何,是否可以優(yōu)化,如何更進一步提升資源利用率,降低機器資源成本?
某大型活動,需要申請多少資源?是否不需要壓測,或者自動化利用線上流量數(shù)據(jù),或者利用日常壓測數(shù)據(jù),就可以給出上述問題的結(jié)論?
如何保證服務(wù)穩(wěn)定性,如何監(jiān)控服務(wù)性能劣化并及時預警,限流、超時、重試以及熔斷等服務(wù)治理措施配置是否合理?以及如何配合混沌測試進行容災演練,保證服務(wù)穩(wěn)定性等等,這些 Rhino 平臺都會做更進一步探索。
目前 Rhino 團隊還非常小,非常缺少性能測試以及后端開發(fā)相關(guān)的研發(fā)工程師,歡迎感興趣的同學來加入。簡歷投遞郵箱: 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
品質(zhì)優(yōu)化 - 圖文詳情頁秒開實踐
Android Camera 內(nèi)存問題剖析
字節(jié)跳動自研線上引流回放系統(tǒng)的架構(gòu)演進
歡迎關(guān)注「字節(jié)跳動技術(shù)團隊」
得不佩服,美觀小巧的網(wǎng)頁內(nèi)容編輯器——ContentTools
愛分享Coder
2019-12-03 · 軟件開發(fā)工程師 優(yōu)質(zhì)科技領(lǐng)域創(chuàng)作者
ContentTools是一個美觀小巧的網(wǎng)頁內(nèi)容工具(一個JS庫),具備所見即所得(WYSIWYG)的編輯器功能,只需幾個簡單的步驟,即可將ContentTools添加到任何HTML頁面。如下圖所示頁面通過實時ContentTool的彈出層實現(xiàn)實時編輯功能。用小而美來形容它最好不過了!
https://github.com/GetmeUK
ContentTools是用于HTML頁面的美觀小巧的內(nèi)容編輯器。它被設(shè)計為:
ContentTools具有字體加粗、斜體、超鏈接、對齊、列表、表格、圖片、視頻、代碼、撤銷、重做、刪除等功能
1、加粗顯示
2、斜體顯示
3、超鏈接
4、H標題
5、正文
6、有序和無序列表
7、插入表格
8、插入圖片
9、視頻
以上截圖中的功能還不完整,如果想體驗以下完整的功能可以直接去DEMO頁面體驗,如果需要在HTML級別上更改元素的內(nèi)容,那也是可以的。通過屬性對話框中的最后一個選項卡,可以查看所選元素的內(nèi)部HTML代碼并直接對其進行更新。
下載倉庫并打開/ build文件夾,包括預構(gòu)建的源文件。將文件夾的內(nèi)容復制到項目的適當位置(例如,content-tools.min.js>
/www/scripts/content-tools.min.js)。但是,/ images文件夾和icons.woff字體需要復制到與content-tools.min.css相同的文件夾中,文件結(jié)構(gòu)應(yīng)類似于:
<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文件。包含初始化我們的編輯器的代碼,繼續(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屬性用于在保存時標識區(qū)域(默認情況下使用id屬性),標記可編輯HTML時,常見的誤解是將單個元素標記為可編輯,例如:
<h1 data-editable data-name="heading">Content</h1>
正確的使用方式如下,也就是說必須要在特定的容器元素內(nèi)
<div data-editable data-name=heading>
<h1>Content</h1>
</div>
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;
}
/* 可編輯區(qū)域中文本的對齊樣式 */
[data-editable] .text-center {
text-align: center;
}
[data-editable] .text-left {
text-align: left;
}
[data-editable] .text-right {
text-align: right;
}
ContentTools提供了一個編輯器,但是在初始化它之前,我們需要配置一些東西,即:
將以下代碼添加到我們之前創(chuàng)建的editor.js文件中:
window.addEventListener('load', function() {
var editor;
});
就像文字處理程序一樣,可以為內(nèi)容配置一系列預定義樣式。當用戶從視口底部的檢查器欄中選擇標簽時,這些標簽就會出現(xiàn)。盡管可以將樣式設(shè)置為適用于所有標簽,但是僅顯示適用于標簽類型的樣式。
我們將添加可應(yīng)用于段落<p>標記的單一樣式.author。在var編輯器下方聲明添加:
ContentTools.StylePalette.add([
new ContentTools.Style('Author', 'author', ['p'])
]);
StylePalette.add方法使我們可以向編輯器添加樣式列表。每種樣式均聲明為一個Style實例,該實例使用顯示名稱,CSS類和可以應(yīng)用該樣式的標簽列表初始化。我們需要添加相關(guān)的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');
我們使用用于頁面可編輯區(qū)域的CSS選擇器和屬性名稱(“數(shù)據(jù)名稱”)來初始化編輯器,以告知編輯器元素的哪個屬性包含其區(qū)域名稱。區(qū)域名稱在同一頁面中必須唯一。
最后,我們希望在用戶保存頁面時得到通知,以便我們可以將每個區(qū)域的更新內(nèi)容存儲在文件或數(shù)據(jù)庫中。為此,我們監(jiān)聽由編輯器觸發(fā)的保存事件。在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;
}
// 保存更改時將編輯器設(shè)置為忙
this.busy(true);
// 將每個區(qū)域的內(nèi)容收集到一個FormData實例中
payload=new FormData();
for (name in regions) {
if (regions.hasOwnProperty(name)) {
payload.append(name, regions[name]);
}
}
// 將更新內(nèi)容發(fā)送到要保存的服務(wù)器
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將每個區(qū)域的內(nèi)容發(fā)送到服務(wù)器進行保存。在瀏覽器中打開頁面,尋找左上方的藍色編輯按鈕,然后單擊它以開始編輯。
這樣一個美觀且強大的即時編輯器可謂是非常的實用,特別是對于一些內(nèi)容編輯網(wǎng)站,如CMS、靜態(tài)文檔網(wǎng)站、博客等內(nèi)容型網(wǎng)站尤其有用,希望對你有所幫助,Enjoy it!
1.5萬閱讀
搜索
專門制作文字特效軟件
網(wǎng)站制作微信小程序
html5編輯軟件排行榜
傻瓜式網(wǎng)頁制作軟件
網(wǎng)站制作軟件免費版
一鍵網(wǎng)站制作app
實現(xiàn)css兩端對齊,我在網(wǎng)上找了很多方法,都不怎么實用,都是兼容性鬧得,column是css3的屬性,是多列布局,使用column來實現(xiàn)兩端對齊簡單實用,就要設(shè)置下模塊的個數(shù)跟column的列數(shù)一致就行,先看它的的3個屬性:
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 以及更早的版本不支持多列屬性。
實現(xiàn)css兩端對齊的例子:用column-count定義對象的列數(shù),例子中有4個p(即4個模塊),那么就定義為4列,再用column-gap定義了對象中列與列的間距,間距不能設(shè)置為百分比,但是只能用px,具體的看下面的代碼:
<!Doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk2312"/>
<title>實現(xiàn)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)
除注明外的文章,均為來源:湯久生博客,轉(zhuǎn)載請保留本文地址!
原文地址:http://tangjiusheng.com/css3/130.html
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。