Python 版 APM 服務(wù)使用測(cè)試
后端開(kāi)發(fā)與云服務(wù)
云服務(wù)這個(gè)詞,大概最早是從云盤(pán)開(kāi)始的,那時(shí)候概念也特別簡(jiǎn)單,無(wú)非就是把一些數(shù)據(jù)存在別人的服務(wù)器上,在”云存儲(chǔ)”這個(gè)名詞火起來(lái)之前,QQ 也有提供網(wǎng)站的功能用來(lái)存一些小東西(05年06年的樣子,那時(shí)候大概只有幾十 M 的空間),其實(shí)剛聽(tīng)到這個(gè)概念的時(shí)候我就很不理解,光存存東西不至于吹得這么玄乎吧。畢業(yè)后入行,云服務(wù)器才慢慢真真的豐富起來(lái),從最開(kāi)始的 VPS 變成云服務(wù)器、存儲(chǔ)變成資源服務(wù)器、遠(yuǎn)程數(shù)據(jù)庫(kù)等等,現(xiàn)在甚至有幫你防 DDOS 的服務(wù)(去年和今年貌似 DDOS 變得越來(lái)越?jīng)]有節(jié)操了)。確實(shí)節(jié)省了很多精力,也省錢(qián)。
除了云,最近幾年還有另外一個(gè)比較火的詞:"大數(shù)據(jù)”。我沒(méi)接觸過(guò)那么大的數(shù)據(jù),作為一個(gè)半吊子運(yùn)維,接觸的***的數(shù)據(jù)應(yīng)該就是服務(wù)器 log 了。所以大數(shù)據(jù)的東西以后有機(jī)會(huì)接觸再說(shuō),對(duì)我來(lái)說(shuō)更重要的是 — 數(shù)據(jù)統(tǒng)計(jì)。
服務(wù)端的各種 log 不僅是分析服務(wù)器的狀態(tài)的重要參數(shù),也是從后臺(tái)代碼里抓 bug 抓異常檢查 SQL 性能等各種工作的參考。log 數(shù)據(jù)一般都是單調(diào)而且重復(fù)的居多,要發(fā)現(xiàn)它的價(jià)值,往往需要大量的分析和統(tǒng)計(jì)工作。各種監(jiān)控服務(wù)、分析工具也是層出不窮。不過(guò)到今年我才知道有個(gè)詞叫 "APM"。
APM (Application Performance Management/Monitoring) 簡(jiǎn)單翻譯過(guò)來(lái)就是"應(yīng)用性能管理/監(jiān)控”(也許說(shuō)監(jiān)控更準(zhǔn)確一些)。大概就是服務(wù)器上部署的 awstats、nagios、zabbix 等一堆東西的集合。有服務(wù)器的地方就有云,既然這個(gè)事情這么麻煩,那就自然也可以交給別人來(lái)做了。
前幾天找到了一個(gè) Python 的小 web 框架:bottle,只 有一個(gè)文件,簡(jiǎn)潔好用,覺(jué)得很不錯(cuò),先是用它來(lái)做了一個(gè)簡(jiǎn)單的小應(yīng)用(APP 下載,公司內(nèi)部使用),準(zhǔn)備這段時(shí)間嘗試用它來(lái)自己寫(xiě)一個(gè)簡(jiǎn)單的博客系統(tǒng),改造一下自己的博客,所以業(yè)務(wù)時(shí)間花在搞 Python 上的比較多一點(diǎn)。恰好看到了在測(cè) Python 版本的探針,于是部署來(lái)測(cè)試一下。部署之前先在本地做了一些測(cè)試,不過(guò)聽(tīng)云目前僅支持基于 django 開(kāi)發(fā)的程序(文檔上寫(xiě)的目標(biāo)是支持所有以 wsgi 協(xié)議部署的 Python Web 服務(wù),包括 flask、tornado 等等,不過(guò)這個(gè)應(yīng)該還要等后續(xù)開(kāi)發(fā)支持了),所以我就先在本地用 django 測(cè)了一下。
聽(tīng)云探針(Python版)的使用
探針部署過(guò)程十分簡(jiǎn)單,在聽(tīng)云后臺(tái)復(fù)制自己賬戶的 license key,生成配置文件,將配置文件地址加載到環(huán)境變量中,就可以啟動(dòng)程序開(kāi)始使用了。以下是測(cè)試環(huán)境部署步驟的介紹。
先用 virtualenv 開(kāi)辟一個(gè)環(huán)境并 active 之:
virtualenv tingyun cd tingyun source bin/active
聽(tīng)云探針在 pypi 的倉(cāng)庫(kù)里有,所以可以直接安裝了,同時(shí)也安裝 django , 探針支持 MySQL 的 log 記錄,所以我也安裝了 MySQL 的組件并將 django 的數(shù)據(jù)庫(kù)從 sqlite 改成 MySQL:
# 安裝組件 pip install tingyun django MySQL-python # 創(chuàng)建一個(gè) django 工程 django-admin startproject www
接著需要修改一下 django 的數(shù)據(jù)庫(kù)選項(xiàng),進(jìn)入到 www/www 目錄,打開(kāi) settings.py,找到 DATABASE 的字典,注釋掉原有的 sqlite 選項(xiàng)并改為 MySQL:
# 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django', 'USER': 'root', 'PASSWORD': '', 'HOST': '', 'PORT': '', }
在 MySQL 中創(chuàng)建 django 的庫(kù),然后安裝 django 的 admin 后臺(tái)需要的數(shù)據(jù)表(注意回到 manage.py 所在的目錄):
python manage.py syncdb
接下來(lái)設(shè)置聽(tīng)云的服務(wù),按照聽(tīng)云后臺(tái)的提示和文檔說(shuō)明進(jìn)行就可以了:
# YourLicenseKey 是你的聽(tīng)云后臺(tái)里顯示的 key # 聽(tīng)云后臺(tái)里將 tingyun.ini 放置在 tmp 目錄,我建議你放在當(dāng)前工作目錄,免得丟失 # 一些配置參數(shù)可以打開(kāi) tingyun.ini 進(jìn)行修改 tingyun-admin generate-config YourLicenseKey tingyun.ini # # 這里的 TING_YUN_CONFIG_FILE 寫(xiě)絕對(duì)路徑比較保險(xiǎn),以下是我本地的目錄 # 如果是在服務(wù)器上,可以寫(xiě)入到 .bashrc 或者 .bash_profile 中去,需要重啟服務(wù)時(shí)不用重新設(shè)置 export TING_YUN_CONFIG_FILE=/Users/Scholer/Work/Personal/tingyun/tingyun.ini # # 聽(tīng)云的服務(wù)會(huì)讀取當(dāng)前環(huán)境變量的參數(shù) TING_YUN_CONFIG_FILE 來(lái)獲取配置文件 # 我們可以先檢查一下,如果看到 success 字樣就 OK tingyun-admin check-config
萬(wàn)事具備,可以啟動(dòng)服務(wù)了:
tingyun-admin run-program python www/manage.py runserver
接下來(lái)我們就可以瀏覽一下頁(yè)面,登錄一下后臺(tái)等等生成一些訪問(wèn)記錄來(lái)看看效果了(或者可以比較殘暴一點(diǎn)用測(cè)試工具,我用 ab 發(fā)了一些的測(cè)試請(qǐng)求)。
一切順利的話,過(guò)一會(huì)兒刷新一下聽(tīng)云的后臺(tái),就能看到一些數(shù)據(jù)了。
有一些事情需要注意一下:
- 聽(tīng)云的多個(gè)應(yīng)用是同一個(gè) key,通過(guò)應(yīng)用名稱來(lái)區(qū)分應(yīng)用;
- 不同于一些其他服務(wù)、聽(tīng)云沒(méi)有新建一個(gè) 應(yīng)用的過(guò)程,有部署、上報(bào)的數(shù)據(jù)就能看到數(shù)據(jù)了;
- 如果使用 uwsgi 的方式不是,需要開(kāi)啟
enable-threads
和single-interpreter
的選項(xiàng)。
上報(bào)數(shù)據(jù)觀察
登錄到聽(tīng)云的后臺(tái)管理面板就能查看到一些監(jiān)控日志分析了(圖表是用 highcharts 做的,體驗(yàn)相當(dāng)不錯(cuò))。
圖中可以看到一些基本的數(shù)據(jù)圖表,包括應(yīng)用的響應(yīng)時(shí)間、Apdex(應(yīng)用程序性能指數(shù)),應(yīng)用響應(yīng)耗時(shí)和吞吐率等等。
此外面板上也會(huì)有硬件的基本信息,包括 CPU 的占用時(shí)間、內(nèi)存占用等參數(shù)。
各項(xiàng)參數(shù)指標(biāo)的統(tǒng)計(jì)最終目的都是為了分析服務(wù)器本身的承載能力和性能。當(dāng)以上參數(shù)出現(xiàn)異常情況,比如響應(yīng)時(shí)間過(guò)長(zhǎng)、CPU負(fù)載過(guò)高或者內(nèi)存剩余不多時(shí),就要考慮升級(jí)硬件資源或者對(duì)程序進(jìn)行優(yōu)化了。
Apdex (Application Performance Index) ,應(yīng)用性能指數(shù)。這是一個(gè)近幾年成立的聯(lián)盟組織,大概是在 2010 年發(fā)起的,12 年之后沉寂了兩年,去年又開(kāi)始活躍了。這個(gè)聯(lián)盟意在通過(guò)一個(gè)統(tǒng)一的標(biāo)準(zhǔn)來(lái)計(jì)算和衡量應(yīng)用程序的的性能,在它的 官網(wǎng) 中有一些專門(mén)的文章來(lái)介紹自己。
"Apdex is a way to study measurements of any experience that can be interpreted on a scale ranging from excellent to unacceptable. " (Apdex 用以學(xué)習(xí)解釋從好到壞的評(píng)級(jí)標(biāo)準(zhǔn)的相關(guān)經(jīng)驗(yàn)。)
Apdex 的計(jì)算在下面這篇文章用也有介紹:
Apdex = (正常樣本 + 0.5 x 低質(zhì)樣本 + 0 x 高質(zhì)樣本) / 樣本總量
我們可以這樣把正常樣本理解成正常的時(shí)間,低質(zhì)和高質(zhì)就分別表示響應(yīng)的慢和快。顯然計(jì)算結(jié)果從 1 到 0 就表示從好到壞。
詳細(xì)介紹:http://www.apdex.org/index.php/2014/05/apdex-is-not-just-for-application-performance/
以上兩張統(tǒng)計(jì)圖分別展示了應(yīng)用層的處理時(shí)間與數(shù)據(jù)庫(kù)調(diào)用時(shí)間。這兩個(gè)參數(shù)是對(duì)程序和 SQL 語(yǔ)句進(jìn)行優(yōu)化的重要參考。這里應(yīng)該是計(jì)算的平均時(shí)間。
在實(shí)際的分析過(guò)程中,我們也同樣需要對(duì)于所有耗時(shí)過(guò)長(zhǎng)的處理或者 SQL 慢查詢進(jìn)行分析和優(yōu)化。聽(tīng)云也提供了對(duì)于耗時(shí)應(yīng)用和 SQL 的統(tǒng)計(jì)。
在上面的"最耗時(shí)的應(yīng)用過(guò)程"中,有一個(gè)墻鐘時(shí)間比的概念。墻鐘時(shí)間(Wall-clock time / wall time)指的是程序從開(kāi)始執(zhí)行到結(jié)束的過(guò)程中人的時(shí)間感知(這個(gè)時(shí)間是大于 CPU 時(shí)間的,由系統(tǒng)提供)。墻鐘時(shí)間比就表示當(dāng)前時(shí)間點(diǎn)下某個(gè)程序占總墻鐘時(shí)間的百分比。
除了常見(jiàn)關(guān)系型數(shù)據(jù)庫(kù)的監(jiān)控,聽(tīng)云也提供了對(duì) memcached、Redis、MongoDB 等非關(guān)系型數(shù)據(jù)庫(kù)的監(jiān)控和統(tǒng)計(jì)。
響應(yīng)率和吞吐率參數(shù)參數(shù)。吞吐率指的是單位時(shí)間內(nèi)響應(yīng)的數(shù)量。這兩個(gè)參數(shù)是對(duì)網(wǎng)站總體的響應(yīng)速度和承載能力的評(píng)估。
吞吐量、響應(yīng)時(shí)間、Apdex和錯(cuò)誤率的概覽。
聽(tīng)云后臺(tái)的參數(shù)記錄十分全面,從硬件基礎(chǔ)到程序響應(yīng)到數(shù)據(jù)庫(kù)執(zhí)行耗時(shí)都有完整的分析和記錄。不過(guò)遺憾的是在后臺(tái)沒(méi)有看到 HTTP 狀態(tài)碼的記錄,類似 awstats 提供的記錄和統(tǒng)計(jì)功能。不過(guò)相對(duì)于一個(gè)需要自己做復(fù)雜的配置的開(kāi)源組件,優(yōu)勢(shì)還是十分明顯的。我也相信隨著時(shí)間的推移,服務(wù)會(huì)越來(lái)越豐富,這些信息都會(huì)被 記錄并分析出來(lái)。
簡(jiǎn)析
部署和數(shù)據(jù)分析都說(shuō)了,現(xiàn)在也可以簡(jiǎn)單的來(lái)分析下聽(tīng)云是如何運(yùn)作的。我無(wú)意去弄清楚探針工作的每一個(gè)步驟,但卻可以了解一下大致的流程。
Python 作為一門(mén)膠水語(yǔ)言,已經(jīng)積淀了豐富的優(yōu)秀模塊,歷來(lái)都是被公認(rèn)為作為服務(wù)端運(yùn)維***力的腳本語(yǔ)言,對(duì)于這類問(wèn)題的處理上,具有天然的優(yōu)勢(shì)。聽(tīng)云在語(yǔ)言上也做了處理,能夠同時(shí)支持 Python 2 和 Python 3。
在聽(tīng)云的配置文件 tingyun.ini 中,除了有 license_key
以外,還有 app_name
、 log_file
、 log_level
等參數(shù)配置。其中 action_tracer.log_sql
可以選擇是否將 SQL 日志只保存在本地文件中(這應(yīng)該是出于安全考慮,畢竟把所有的 SQL 日志都暴漏給服務(wù)平臺(tái),有些人可能會(huì)有些顧慮。但是考慮到現(xiàn)在服務(wù)器一般都是云服務(wù)器,所以這其實(shí)問(wèn)題也并不大,選擇了服務(wù),就應(yīng)該相信服務(wù)),這點(diǎn)聽(tīng)云考慮的很周到。
log 文件中記錄了一些 trace 的log,包括程序耗時(shí)等。
回到程序本身中去,在啟動(dòng)探針的時(shí),我們執(zhí)行的是 tingyun run-program
,最終執(zhí)行的是聽(tīng)云的 package 中 admin 目錄下的 run_program
的函數(shù),check_config
、generate_config
也位于 admin 目錄下。整個(gè)程序目錄還包括 bootstrap 、hook 和 api 目錄。
root_directory = os.path.dirname(root_directory) boot_directory = os.path.join(root_directory, 'bootstrap') python_path = boot_directory
run_program
將 bootstrap 目錄加入系統(tǒng) path 中。通過(guò) Python 提供的兩個(gè) hook(sitecustomize 和 usercustomize 之中的 sitecustomize,聽(tīng)云探針正式被加載到運(yùn)行環(huán)境中:
if config_file is not None: # When installed as an egg with buildout, the root directory for # packages is not listed in sys.path and scripts instead set it # after Python has started up. This will cause importing of # 'tingyun' module to fail. if root_directory not in sys.path: sys.path.insert(0, root_directory) import tingyun.agent # Finally initialize the agent. tingyun.agent.initialize(config_file=config_file)
在 tingyun.api.initial.config
中,initialize
函數(shù)被執(zhí)行,調(diào)用 _process_module_builtin
函數(shù),探針開(kāi)始工作 :
_load_configuration(config_file=config_file) if not _detect_done: _detect_done = True _process_module_builtin()
MySQL、Redis 等監(jiān)控模塊都位于 hook 目錄下,通過(guò) _process_module_definition_wrapper
函數(shù)將進(jìn)程與監(jiān)控模塊進(jìn)行綁定,包括 django 的主要模塊以及常用的數(shù)據(jù)庫(kù)等。在核心模塊執(zhí)行的時(shí)候觸發(fā)監(jiān)控,將數(shù)據(jù)回傳到 api.tracert
模塊進(jìn)行處理。
而對(duì)于硬件信息的檢測(cè)則由 api.platform.system_info
進(jìn)行。
應(yīng)用監(jiān)控?cái)?shù)據(jù)最終會(huì)由 api.tracert.uploader
上傳到聽(tīng)云的服務(wù)器(host 的設(shè)置位于 api.settings
中,host 地址是 redirect.networkbench.com,所以看到你的服務(wù)器往這個(gè)域名發(fā)送請(qǐng)求時(shí),不要覺(jué)得奇怪),通過(guò)聽(tīng)云的處理,我們就能看到應(yīng)用程序的各種監(jiān)控?cái)?shù)據(jù)了。
對(duì)聽(tīng)云探針的簡(jiǎn)單分析就到這里,有興趣的讀者可以進(jìn)一步深入研究。其實(shí)對(duì)于這類云服務(wù),程序的本身都是透明的,不用有太大的安全顧慮,對(duì)于服務(wù)提供方而言,更重要的是數(shù)據(jù)的分析工作。
聽(tīng)云本身提供的服務(wù)器是非常優(yōu)秀的,雖然目前還并非***。我也期待服務(wù)能更加完善,提供更完善的數(shù)據(jù)分析。另外一方面,通過(guò) tingyun-admin run-program
的方式啟動(dòng)程序,對(duì)開(kāi)發(fā)者和服務(wù)器管理員來(lái)說(shuō)可能有些侵入感。如果能用模塊加載的方式調(diào)用,或許更符合某些開(kāi)發(fā)者的習(xí)慣。