這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
自從Go 1.5開始,每次Go release, Gopher Brian Hatfield都會將自己對新版Go的runtime的效能資料(與之前Go版本的比較)在twitter上曬出來。就連Go team staff在世界各地做speaking時也在slide中引用Brian的圖片。後來,Brian Hatfield將其用於度量runtime效能資料的代碼打包成library並放在github上開源了,我們也可以使用這個library來建立我們自己的Go Runtime metrics設施了。這裡簡要說一下搭建的步驟。
一、環境與原理
Brian Hatfield的go-runtime-metrics library實現的很簡單,其runtime data來自於Go runtime package中的MemStats、NumGoroutine和NumCgoCall等。被測試目標程式只需要import該library即可輸出runtime states資料:
import _ "github.com/bmhatfield/go-runtime-metrics"
go-runtime-metrics library將啟動一個單獨的goroutine,並定時上報runtime資料。目前該library僅支援向statsD輸出資料,使用者可以通過配置將statsD的資料匯入graphite並使用graphite web查看,流程如:
本次實驗環境為ubuntu 16.04.1:
$ uname -rmntonybai-ThinkCentre-M6600s-N000 4.4.0-83-generic x86_64
二、搭建步驟
1、安裝go-runtime-metrics library
我們直接go get就可以下載go-runtime-metrics library:
$ go get github.com/bmhatfield/go-runtime-metrics
我們編寫一個目標程式:
//main.gopackage mainimport ( "flag" "log" "net/http" "os" _ "github.com/bmhatfield/go-runtime-metrics")func main() { flag.Parse() cwd, err := os.Getwd() if err != nil { log.Fatal(err) } srv := &http.Server{ Addr: ":8000", // Normally ":443" Handler: http.FileServer(http.Dir(cwd)), } log.Fatal(srv.ListenAndServe())}
我的ubuntu主機上安裝了四個go版本,它們分別是go 1.5.4、go 1.7.6、go 1.8.3和go1.9beta2,於是我們分別用這四個版本的server作為被測程式進行go runtime資料上報,以便對比。
$ GOROOT=~/.bin/go154 ~/.bin/go154/bin/go build -o server-go154 main.go$ GOROOT=~/.bin/go174 ~/.bin/go174/bin/go build -o server-go174 main.go$ GOROOT=~/.bin/go183 ~/.bin/go183/bin/go build -o server-go183 main.go$ GOROOT=~/.bin/go19beta2 ~/.bin/go19beta2/bin/go build -o server-go19beta2 main.go$ ls -l-rwxr-xr-x 1 tonybai tonybai 6861176 7月 4 13:49 server-go154-rwxrwxr-x 1 tonybai tonybai 5901876 7月 4 13:50 server-go174-rwxrwxr-x 1 tonybai tonybai 6102879 7月 4 13:51 server-go183-rwxrwxr-x 1 tonybai tonybai 6365648 7月 4 13:51 server-go19beta2
2、安裝、配置和運行statsD
statsD這個工具用於收集統計資訊,並將彙總後的資訊發給後端服務(比如:graphite)。statsD是採用js實現的服務,因此需要安裝nodejs、npm和相關modules:
$ sudo apt-get install nodejs$ sudo apt-get install npm
接下來,我們將statsD項目clone到本地並根據exampleConfig.js模板配置一個我們自己用的goruntimemetricConfig.js(基本上就是保留預設配置):
// goruntimemetricConfig.js{ graphitePort: 2003, graphiteHost: "127.0.0.1", port: 8125, backends: [ "./backends/graphite" ]}
啟動statsD:
$ nodejs stats.js goruntimemetricConfig.js3 Jul 11:14:20 - [7939] reading config file: goruntimemetricConfig.js3 Jul 11:14:20 - server is up INFO
啟動成功!
3、安裝、配置和運行graphite
graphite是一種儲存時序監控資料,並可以按使用者需求以圖形化形式展示資料的工具,它包括三個組件:
whisper是一種基於file的時序資料庫格式,同時whisper也提供了相應的命令和API供其他組件調用以操作時序資料庫;
carbon用於讀取外部推送的metrics資訊,進行彙總並寫入db,它還支援緩衝熱點資料,提升訪問效率。
graphite-web則是針對使用者的圖形化系統,用於定製展示監控資料的。
Graphite的安裝和配置是略微繁瑣的,我們一步一步慢慢來。
a) 安裝graphite
$sudo apt-get install graphite-web graphite-carbonwhisper將作為依賴自動被安裝。
b) local_settings.py
graphite的主設定檔在/etc/graphite/local_settings.py,檔案裡面有很多配置項,這裡僅列出有關的,且本次生效的配置:
// /etc/graphite/local_settings.pyTIME_ZONE = 'Asia/Shanghai'LOG_RENDERING_PERFORMANCE = TrueLOG_CACHE_PERFORMANCE = TrueLOG_METRIC_ACCESS = TrueGRAPHITE_ROOT = '/usr/share/graphite-web'CONF_DIR = '/etc/graphite'STORAGE_DIR = '/var/lib/graphite/whisper'CONTENT_DIR = '/usr/share/graphite-web/static'WHISPER_DIR = '/var/lib/graphite/whisper'LOG_DIR = '/var/log/graphite'INDEX_FILE = '/var/lib/graphite/search_index' # Search index fileDATABASES = { 'default': { 'NAME': '/var/lib/graphite/graphite.db', 'ENGINE': 'django.db.backends.sqlite3', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '' }}
c) 同步資料庫
接下來執行下面兩個命令來做database sync(同步):
$ sudo graphite-manage migrate auth.. ....Operations to perform: Apply all migrations: authRunning migrations: Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0001_initial... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK$ sudo graphite-manage syncdbOperations to perform: Synchronize unmigrated apps: account, cli, render, whitelist, metrics, url_shortener, dashboard, composer, events, browser Apply all migrations: admin, contenttypes, tagging, auth, sessionsSynchronizing apps without migrations: Creating tables... Creating table account_profile Creating table account_variable Creating table account_view Creating table account_window Creating table account_mygraph Creating table dashboard_dashboard Creating table events_event Creating table url_shortener_link Running deferred SQL... Installing custom SQL...Running migrations: Rendering model states... DONE Applying admin.0001_initial... OK Applying sessions.0001_initial... OK Applying tagging.0001_initial... OKYou have installed Django's auth system, and don't have any superusers defined.Would you like to create one now? (yes/no): yesUsername (leave blank to use 'root'):Email address: xx@yy.comPassword:Password (again):Superuser created successfully.
這裡我們建立一個superuser:root,用於登入graphite-web時使用。
d) 配置carbon
涉及carbon的設定檔如下,我們保持預設配置不動:
/etc/carbon/carbon.conf(內容太多,這裡不列出來了)/etc/carbon/storage-schemas.conf[carbon]pattern = ^carbon\.retentions = 60:90d[default_1min_for_1day]pattern = .*retentions = 60s:1d[stats]pattern = ^stats.*retentions = 10s:6h,1min:6d,10min:1800d
carbon有一個cache功能,我們通過下面步驟可以將其開啟:
開啟carbon-cache使能開關:$ vi /etc/default/graphite-carbonCARBON_CACHE_ENABLED=true啟動carbon-cache:$ sudo cp /usr/share/doc/graphite-carbon/examples/storage-aggregation.conf.example /etc/carbon/storage-aggregation.conf$ systemctl start carbon-cache
e) 啟動graphite-web
graphite-web支援多種主流web server,這裡以apache2為例,graphite-web將mod-wsgi方式部署在apache2下面:
$sudo apt-get install apache2 libapache2-mod-wsgi$ sudo service apache2 start$ sudo a2dissite 000-defaultSite 000-default disabled.$ sudo service apache2 reload$ sudo cp /usr/share/graphite-web/apache2-graphite.conf /etc/apache2/sites-available$ sudo a2ensite apache2-graphiteEnabling site apache2-graphite.To activate the new configuration, you need to run: service apache2 reload$ sudo systemctl reload apache2
由於apache2的Worker process預設以www-data:www-data使用者權限運行,但資料庫檔案的存取權限卻是:_graphite:_graphite:
$ ll /var/lib/graphite/graphite.db-rw-r--r-- 1 _graphite _graphite 72704 7月 3 13:48 /var/lib/graphite/graphite.db
我們需要修改一下apache worker的user:
$ sudo vi /etc/apache2/envvarsexport APACHE_RUN_USER=_graphiteexport APACHE_RUN_GROUP=_graphite
重啟apache2生效!使用Browser開啟:http://127.0.0.1,如無意外,你將看到下面graphite-web的首頁:
三、執行benchmarking
這裡我將使用wrk這個http benchmarking tool分別對前面的四個版本的目標程式(server-go154 server-go174 server-go183 server-go19beta2)進行benchmarking test,每個目標程式接收10分鐘的請求:
$ ./server-go154$ wrk -t12 -c400 -d10m http://127.0.0.1:8000$ ./server-go174$ wrk -t12 -c400 -d10m http://127.0.0.1:8000$ ./server-go183$ wrk -t12 -c400 -d10m http://127.0.0.1:8000$ ./server-go19beta2$ wrk -t12 -c400 -d10m http://127.0.0.1:8000
四、結果展示
用瀏覽器開啟graphite-web,在左邊的tree標籤下以此開啟樹形結構:Metrics -> stats -> gauges -> go -> YOUR_HOST_NAME -> mem -> gc -> pause,如果順利的話,你將會在Graphite Composer視窗看到折線圖,我們也以GC pause為例,GC pause也是gopher們最為關心的:
通過這幅圖(左側座標軸的單位為nanoseconds),我們大致可以看出:
Go 1.5.4的GC pause約在600μs左右;
Go 1.7.4的GC pause約在300μs左右;
Go 1.8.3和Go 1.9beta2的GC pause基本都在100μs以下了。Go 1.9的GC改進似乎不大。不過這裡我的程式也並不足夠典型。
其他結果:
Go routines number:
GC count:
memory allocations:
除了查看單個指標曲線,你也可以通過graphite-web提供的dashboard功能定製你要monitor的面板,這裡就不贅述了。
五、參考資料
- How to Setup Graphite with Statsd on an Ubuntu 16.04
微博:@tonybai_cn
公眾號:iamtonybai
github.com: https://github.com/bigwhite
2017, bigwhite. 著作權.