.Net微服务实战之可观测性
前言
很多次去面試,有經(jīng)驗的面試官都會問一個問題,你是怎么去定位日常遇到的問題?平常跟同行分享自己遇到的問題,事后他會問我,這種看起來毫無頭緒的問題,你是怎么去定位解決的?
其實(shí)我們平常不知道怎么問題出在哪,主要是所了解的信息量不足,那么怎么才能提高給咱們定位問題的信息量呢?其實(shí)上面兩個問題的答案都是同一個:日志、指標(biāo)、跟蹤。
有日志記錄才能清楚知道當(dāng)前系統(tǒng)的運(yùn)行狀況和具體問題;指標(biāo)是給與后續(xù)做優(yōu)化和定位偶發(fā)性問題的一些參考,沒指標(biāo)參考就沒標(biāo)準(zhǔn);我們平常做得多的調(diào)試、查看調(diào)用棧也是跟蹤的一種,但是在分布式時代,更多考量的是跨進(jìn)程通信的調(diào)用鏈路。
日志、指標(biāo)、跟蹤三者結(jié)合起來有一種統(tǒng)稱——可觀測性
運(yùn)維是架構(gòu)的地基,我第一次看到這句是在張輝清寫的《小團(tuán)隊構(gòu)建大網(wǎng)站:中小研發(fā)團(tuán)隊架構(gòu)實(shí)踐》,說實(shí)話,我非常的認(rèn)同。不少小團(tuán)隊的運(yùn)維都是由開發(fā)兼職的,而團(tuán)隊的運(yùn)維能力決定了日后架構(gòu)選型與日常維護(hù)。有良好的運(yùn)維監(jiān)控體系,就有足夠的信息量提供給開發(fā)人員進(jìn)行定位排錯。
可觀測性
可觀測性的意思是可以由系統(tǒng)的外部輸出推斷其內(nèi)部狀態(tài)的程度,在軟件系統(tǒng)中,可觀察性是指能夠收集有關(guān)程序執(zhí)行、模塊內(nèi)部狀態(tài)以及組件之間通信的數(shù)據(jù)。分別由三個方向組成:日志(logging)、跟蹤(?tracing)、指標(biāo)(Metrics)《Metrics, tracing, and logging》
日志(logging)
日志的定義特征是它記錄離散事件,目的是通過這些記錄后分析出程序的行為。
例如:應(yīng)用程序調(diào)試或錯誤消息通過轉(zhuǎn)換文件描述,通過 syslog 發(fā)送到 Elasticsearch;審計跟蹤事件通過 Kafka 推送到 BigTable 等數(shù)據(jù)存儲;或從服務(wù)調(diào)用中提取并發(fā)送到錯誤跟蹤服務(wù)(如 NewRelic)的特定于請求的元數(shù)據(jù)。
跟蹤(?tracing)
跟蹤的定義特征是它處理請求范圍內(nèi)的信息,目的是排查故障。
在系統(tǒng)中執(zhí)行的單個事務(wù)對象生命周期里,所綁定的數(shù)據(jù)或元數(shù)據(jù)。例如:RPC遠(yuǎn)程服務(wù)調(diào)用的持續(xù)時間;請求到數(shù)據(jù)庫的實(shí)際 SQL 查詢語句;HTTP 請求入站的關(guān)聯(lián) ID。
指標(biāo)(Metrics)
指標(biāo)的定義特征是它們是可聚合的,目的是監(jiān)控和預(yù)警。
這些指標(biāo)在一段時間內(nèi),能組成單個邏輯儀表、計數(shù)器或直方圖。例如:隊列的當(dāng)前長度可以被建模為一個量規(guī);HTTP 請求的數(shù)量可以建模為一個計數(shù)器,更新后通過簡單的加法聚合計算;并且可以將觀察到的請求持續(xù)時間建模為直方圖,更新匯總到某個時間段中并建立統(tǒng)計摘要。
代表性產(chǎn)品
日志(logging)基本上是ELK (ElasticSearch, Logstash, Kibana) 技術(shù)棧一家獨(dú)大了,但是Logstash比較重量級的,而輕量級的Filebeat可能更加受大家的青睞。下文里的實(shí)戰(zhàn)部分,我是以EFK(ElasticSearch, Filebeat, Kibana)演示。
跟蹤( tracing)相比于日志就是百花齊放了,Skywalking、zipkin、鷹眼、jeager、Datadog等等……但是在.Net的技術(shù)棧里,能提供出SDK的相對會少,所以選擇也會少一些,我在之前的實(shí)戰(zhàn)和下文的演示都是用Skywalking,主要優(yōu)勢無侵入。
指標(biāo)(Metrics)在云生時代Prometheus比Zabbix更加受大家歡迎,同時Prometheus社區(qū)活躍度也占非常大的優(yōu)勢。下文實(shí)戰(zhàn)部分我以Prometheus 作為演示。
ElasticSearch部署與安裝
后面的Skywaking和日志都需要用到ElasticSearch,所以我把部署流程優(yōu)先提了出來。
導(dǎo)入 GPG key
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch添加源
vim /etc/yum.repos.d/elasticsearch.repo[elasticsearch] name=Elasticsearch repository for 7.x packages baseurl=https://artifacts.elastic.co/packages/7.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=0 autorefresh=1 type=rpm-md重新加載
yum makecache安裝
sudo yum install -y --enablerepo=elasticsearch elasticsearch修改配置
vim /etc/elasticsearch/elasticsearch.ymlnetwork.host: 0.0.0.0discovery.type: single-node啟動
/sbin/chkconfig --add elasticsearchsudo -i service elasticsearch start systemctl enable elasticsearch.service用瀏覽器訪問,能出現(xiàn)下圖就是可以了
Prometheus與Grafana實(shí)現(xiàn)指標(biāo)
架構(gòu)簡析
核心組件
Prometheus server
Prometheus的主程序,本身也是一個時序數(shù)據(jù)庫,它來負(fù)責(zé)整個監(jiān)控集群的數(shù)據(jù)拉取、處理、計算和存儲,是使用pull方式由服務(wù)端主動拉取監(jiān)控數(shù)據(jù)。
Alertmanager
Prometheus的告警組件,負(fù)責(zé)整個集群的告警發(fā)送、分組、調(diào)度、警告抑制等功能。?需要知道的是alertmanager本身是不做告警規(guī)則計算的,簡單來說就是,alertmanager不去計算當(dāng)前的監(jiān)控取值是否達(dá)到我設(shè)定的閾值,上面已經(jīng)提過該部分規(guī)則計算是prometheus server來計算的,alertmanager監(jiān)聽prometheus server發(fā)來的消息,然后在結(jié)合自己的配置,比如等待周期,重復(fù)發(fā)送告警時間,路由匹配等配置項,然后把接收到的消息發(fā)送到指定的接收者。同時他還支持多種告警接收方式,常見的如郵件、企業(yè)微信、釘釘?shù)取?.3
Pushgateway
Pushgateway 它是prometheus的一個中間網(wǎng)管組件,類似于zabbix的zabbix-proxy。它主要解決的問題是一些不支持pull方式獲取數(shù)據(jù)的場景,比如:自定義shell腳本來監(jiān)控服務(wù)的健康狀態(tài),這個就沒辦法直接讓prometheus來拉數(shù)據(jù),這時就可以借助pushgateway,它是支持推送數(shù)據(jù)的,我們可以把對應(yīng)的數(shù)據(jù)按照prometheus的格式推送到pushgateway,然后配置prometheus server拉取pushgateway即可。
UI?
Grafana、prometheus-ui是用來圖形化展示數(shù)據(jù)的組件,其中prometheus-ui是prometheus項目原生的ui界面,但是在數(shù)據(jù)展示方面不太好用,因此推薦grafana來展示你的數(shù)據(jù),grafana支持prometheus的PromQL語法,能夠和prometheus數(shù)據(jù)庫交互,加上grafana強(qiáng)大的ui功能,我們可以很輕松的獲取到很多好看的界面,同時也有很多做好的模版可以使用。
Prometheus Target
采集指標(biāo)的API,有不同的Exporter,如果redis、mysql、server nodel提供給Prometheus server定時pull數(shù)據(jù)到數(shù)據(jù)庫。
安裝Prometheus
mkdir /var/prometheus docker run -d --name=prometheus -p 9090:9090 prom/prometheus docker cp prometheus:/etc/prometheus/prometheus.yml /var/prometheus/刪除之前的容器docker run -d --name=prometheus -p 9090:9090 -v /var/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus到瀏覽器輸入地址訪問,出現(xiàn)以下頁面則成功
?
安裝Grafana
docker run -d --name=grafana -p 3000:3000 grafana/grafana安裝完成后,使用admin/admin登錄
安裝Node Exporter
docker run -d -p 9100:9100 \-v "/proc:/host/proc:ro" \-v "/sys:/host/sys:ro" \-v "/:/rootfs:ro" \--net="host" \--restart always \prom/node-exporter到瀏覽器輸入地址訪問(http://192.168.184.129:9100/metrics),出現(xiàn)以下頁面則成功
配置Prometheus
vim /var/prometheus/prometheus.yml添加以下配置 (注意格式)
??-?job_name:?service-a
????static_configs:
??????-?targets:?["192.168.88.138:9100"]
????????labels:
??????????instance:?node
??-?job_name:?service-b
????static_configs:
??????-?targets:?["192.168.88.146:9100"]
????????labels:
??????????instance:?node
??-?job_name:?service-c
????static_configs:
??????-?targets:?["192.168.88.144:9100"]
????????labels:
??????????instance:?node
重新啟動Prometheus,打開瀏覽器可以見下圖
配置Grafana
添加數(shù)據(jù)源
導(dǎo)入模板,其他模板可以到?https://grafana.com/grafana/dashboards 查看
?確認(rèn)后則生成(注意修改主機(jī)名)
?
到這里完整的一次監(jiān)控就完成,我們可以根據(jù)上訴的步驟添加容器和docker的監(jiān)控。
使用Docker Exporter監(jiān)控容器
用docker進(jìn)行安裝
docker run --name docker_exporter --detach --restart always --volume "/var/run/docker.sock":"/var/run/docker.sock" --publish 9417:9417 prometheusnet/docker_exporter在Prometheus進(jìn)行配置,添加下面配置項
vim /var/prometheus/prometheus.yml- job_name: "container"static_configs:- targets: ["192.168.88.138:9417"]在grafana根據(jù)上面node-exporter的步驟進(jìn)行導(dǎo)入對應(yīng)的模板 https://grafana.com/grafana/dashboards/11467
使用docker metrics 監(jiān)控docker
開啟metrics
vim /etc/docker/daemon.json{"metrics-addr" : "192.168.88.146:9323","experimental" : true }重啟docker
systemctl daemon-reload service docker restart配置Prometheus
- job_name: "docker"static_configs:- targets: ["192.168.88.138:9323", "192.168.88.146:9323", "192.168.88.146:9323"]導(dǎo)入模板https://grafana.com/grafana/dashboards/1229
SkyWalking實(shí)現(xiàn)跟蹤
架構(gòu)簡析
核心組件
Skywalking OAP Server
Skywalking收集器,接受寫入請求與UI數(shù)據(jù)查詢。
Skywalking UI
有調(diào)用鏈路記錄、網(wǎng)絡(luò)拓?fù)鋱D、性能指標(biāo)展示等。
Skywalking客戶端代理
提供了多種語言的SDK(Java, .NET Core, NodeJS, PHP,? Python等),在應(yīng)用程序進(jìn)行網(wǎng)絡(luò)請求的時候進(jìn)行埋點(diǎn)攔截,整理成需要的指標(biāo)發(fā)送到Skywalking OAP Server,
安裝SkyWalking的收集器
docker run --name skywalking-oap-server -p 12800:12800 -p 11800:11800 -p 1234:1234 --restart always -d -e SW_STORAGE=elasticsearch7 -e SW_STORAGE_ES_CLUSTER_NODES=192.168.184.129:9200 apache/skywalking-oap-server:8.4.0-es7啟動成功后去ES查看,多了很多的Index
安裝SkyWalking UI
docker run --name skywalking-ui -p 8888:8080 --restart always -d -e SW_OAP_ADDRESS=192.168.184.129:12800 apache/skywalking-ui:8.4.0使用時注意調(diào)整右下角的時區(qū)
?我們到Github下載源碼?https://github.com/SkyAPM/SkyAPM-dotnet,根據(jù)how-to-build文檔進(jìn)行編譯
- Prepare git and .NET Core SDK. - `git clone https://github.com/SkyAPM/SkyAPM-dotnet.git` - `cd SkyAPM-dotnet/` - Switch to the tag by using `git checkout [tagname]` (Optional, switch if want to build a release from source codes) - `git submodule init` - `git submodule update` - Run `dotnet restore` - Run `dotnet build src/SkyApm.Transport.Grpc.Protocol` - Run `dotnet build skyapm-dotnet.sln`啟動SkyApm.Sample.Frontend與SkyApm.Sample.Backend兩個項目,瀏覽器訪問http://localhost:5001/api/values/postin ,就可以見到下面的調(diào)用鏈了。
我在19年的時候使用0.9版本,http.request_body和http.response_body都是沒記錄需要自己擴(kuò)展,而現(xiàn)在最新版已經(jīng)有記錄,省了不少的事。
EFK(ElasticSearch+Filebeat+Kibana)實(shí)現(xiàn)日志
安裝Nginx
主要用來測試的
添加源
rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm安裝
yum install -y nginx修改配置
vim /etc/nginx/nginx.conf把圈起來的配置改動一下
log_format json '{"@timestamp":"$time_iso8601",''"host": "$server_addr",''"clientip": "$remote_addr",''"request_body": "$request_body",''"responsetime": $request_time,''"upstreamtime": "$upstream_response_time",''"upstreamhost": "$upstream_addr",''"http_host": "$host",''"url": "$uri",''"referer": "$http_referer",''"agent": "$http_user_agent",''"status": "$status"}';access_log /var/log/nginx/access.log json;開機(jī)啟動
systemctl start nginx.service systemctl enable nginx.service用瀏覽器訪問,刷新幾次,執(zhí)行cat /var/log/nginx/access.log 就可以看到j(luò)son格式的日志了
安裝Filebeat
導(dǎo)入安裝源
sudo rpm --import https://packages.elastic.co/GPG-KEY-elasticsearchvim /etc/yum.repos.d/elastic.repo保存下面文案
[elastic-7.x] name=Elastic repository for 7.x packages baseurl=https://artifacts.elastic.co/packages/7.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md執(zhí)行安裝指令
yum install -y filebeat添加配置
vim /etc/filebeat/filebeat.ymlfilebeat.inputs: ??-?type: log ????enabled:?true ????paths: ??????-?/var/log/nginx/access.log ????json.key_under_root:?true ????json.overwrite_keys:?true ????json.message_key: log ????tags: ["nginx-access"] ??-?type: log ????enabled:?true ????paths: ??????-?/var/log/nginx/error.log ????json.key_under_root:?true ????json.overwrite_keys:?true ????json.message_key: log ????tags: ["nginx-error"] filebeat.config.modules: ??path: ${path.config}/modules.d/*.yml ??reload.enabled:?false setup.ilm.enabled:?false setup.template: ??name:?"nginx" ??pattern:?"nginx-*" setup.template.overwrite:?true setup.template.enabled:?false output.elasticsearch: ??hosts: ["192.168.184.129:9200"] ??indices: ????- index:?"nginx-access-%{+yyyy.MM.dd}" ??????when.contains: ????????tags:?"nginx-access" ????- index:?"nginx-error-%{+yyyy.MM.dd}" ??????when.contains: ????????tags:?"nginx-error" |
啟動
systemctl start filebeat systemctl enable filebeat?安裝kibana
docker run --name kibana -d -p 5601:5601 kibana:7.7.0mkdir /var/kibana docker cp kibana:/usr/share/kibana/config /var/kibana/config刪除之前的容器再安裝一次
docker run --name kibana -d -v /var/kibana/config:/usr/share/kibana/config -p 5601:5601 kibana:7.7.0修改配置后,重啟容器
vim /var/kibana/config/kibana.yml?打開瀏覽器訪問
創(chuàng)建索引,填寫nginx-access-*
最后的展示UI
.Net的日志同樣可以使用Json保存,然后通過Filebeat進(jìn)行采集。
總結(jié)
以上是生活随笔為你收集整理的.Net微服务实战之可观测性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在 ASP.NET CORE 中获取
- 下一篇: Dapr牵手.NET学习笔记:发布-订阅