天天看點

服務監控Skywalking的存儲配置與調優

   作為一款APM和全鍊路監控平台,Skywalking算是挺出色的。Skywalking是APM監控平台的後起之秀,大有超越其他開源APM監控平台的趨勢。它通過探針自動收集所需的名額,并進行分布式追蹤。通過這些調用鍊路以及名額,Skywalking APM會感覺應用間關系和服務間關系,并進行相應的名額統計。

        目前Skywalking支援h2、mysql、ElasticSearch作為資料存儲,我就說一下,這三個種庫的優缺點和使用要求:

        1、首先是預設的h2

        h2是Skywalking自帶的,對應的jar包路徑是Skywalking/oap-libs/h2-1.4.196.jar,h2是一種記憶體資料庫,在Skywalking配置檔案的預設配置如下:

h2:

driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}

url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db}

user: ${SW_STORAGE_H2_USER:sa}

metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}

作為記憶體資料庫,當然是儲存在記憶體中,隻要服務重新開機或是Skywalking應用故障了,基本上所監控到的資料也就丢失了,是以h2的記憶體模式其實不适合于應用服務長時間監控的場景。但是h2也可以變為檔案資料庫,配置如下:

url: ${SW_STORAGE_H2_URL:jdbc:h2:tcp://127.0.0.1/~/skywalking-oap-db;AUTO_SERVER=TRUE}

和記憶體模式的配置差別就是URL換成了檔案的路徑,預設路徑是在使用者目錄下(如administrator或root或home/user等使用者目錄)自動建立資料庫檔案skywalking-oap-db。

要使用檔案資料庫,有個前提是要先啟動h2的TCP服務,因為預設skywalking調用的是記憶體資料庫,如果沒有啟動h2 TCP,由于監聽不到端口,oapService就會判斷為連接配接故障而關閉。啟動h2 TCP服務,可以在bin目錄建立啟動腳本,linux腳本如下:

#!/usr/bin/env sh

PRG="$0"

PRGDIR=`dirname "$PRG"`

[ -z "$OAP_HOME" ] && OAP_HOME=`cd "$PRGDIR/.." >/dev/null; pwd`

OAP_LOG_DIR="${OAP_HOME}/logs"

JAVA_OPTS=" -Xms64M -Xmx256M"

if [ ! -d "${OAP_HOME}/logs" ]; then

mkdir -p "${OAP_LOG_DIR}"

fi

_RUNJAVA=${JAVA_HOME}/bin/java

[ -z "$JAVA_HOME" ] && _RUNJAVA=java

CLASSPATH="$OAP_HOME/config:$CLASSPATH"

for i in "$OAP_HOME"/oap-libs/h2*.jar

do

CLASSPATH="$i:$CLASSPATH"

done

OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}"

# 如果需要遠端連接配接h2資料庫,需将-tcp改為-tcpAllowOthers

eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH org.h2.tools.Server -tcp \

2>${OAP_LOG_DIR}/h2Tcp.log 1> /dev/null &"

if [ $? -eq 0 ]; then

sleep 1

echo "SkyWalking h2Tcp started successfully!"

else

echo "SkyWalking h2Tcp started failure!"

exit 1

對應的windows腳本如下:

@REM 如果需要遠端檢視h2資料庫(tcp端口9092,頁面通路端口8082),需将-tcp改為-tcpAllowOthers

@echo off

setlocal

set OAP_PROCESS_TITLE=Skywalking-H2TcpServer

set OAP_HOME=%~dp0%..

set OAP_OPTS="-Xms64M -Xmx256M -Doap.logDir=%OAP_HOME%\logs"

set CLASSPATH=%OAP_HOME%\config;.;

set CLASSPATH=%OAP_HOME%\oap-libs\*;%CLASSPATH%

if defined JAVA_HOME (

set _EXECJAVA="%JAVA_HOME%\bin\java"

)

if not defined JAVA_HOME (

echo "JAVA_HOME not set."

set _EXECJAVA=java

start "%OAP_PROCESS_TITLE%" %_EXECJAVA% "%OAP_OPTS%" -cp "%CLASSPATH%" org.h2.tools.Server -tcp

endlocal

先啟動h2檔案資料庫,確定9092端口能被監聽,再啟動Skywalking的其他服務。

h2檔案資料庫雖然非常輕量級,畢竟skywalking自帶了,但是穩定性卻很差,一但檔案損壞(大并發量和大吞吐量的監控資料,就會把它幹壞),oapService服務就啟動不了了,需要清除檔案或是恢複及覆寫檔案才能啟動(對于一般應用者來說,這也是要命的事)。

       2、Mysql資料庫

       啟用mysql存儲,有兩個地方需要配置,一個是application.yml

mysql:

       另一個是datasource-settings.properties

jdbcUrl=jdbc:mysql://localhost:3306/swtest

dataSource.user=root

dataSource.password=root@1234

       mysql資料庫相對要穩定,畢竟是被大量使用的資料庫,而且可以做相應的優化,配置緩存,加大資料吞吐量。但是基于mysql的查詢速度我覺得不快,特别是skywalking中【追蹤】檢視,3萬條以上的記錄查詢基本上覺得卡。但作為長時間的應用性能監控來說,mysql合适。而對于Linux下的部署來說,mysql偏重量級了(編譯後的二進制mysql安裝包就有好幾百M)。

       3、ElasticSearch

        官網好像是推薦使用ElasticSearch,為什麼推薦?我猜的,應該是快呀。ES(ElasticSearch)是一款分布式全文檢索架構,底層基于Lucene實作,是給搜尋引擎專用的,不快都不行。試了一下10萬條的追蹤記錄,基本上很快就能查詢展示。

        ElasticSearch不是自帶的,需要安裝,考慮到輕量級,我選用的是elasticsearch-6.2.4,原因是包小免安裝,解壓完也才30多M,而且目前最新版本的Skywalking 6.2.0是能夠支援該版本的ElasticSearch。

        Skywalking啟用ES,隻需要配置檔案設定如下:

storage:

elasticsearch:

nameSpace: ${SW_NAMESPACE:""}

clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}

user: ${SW_ES_USER:""}

password: ${SW_ES_PASSWORD:""}

indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}

indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}

# Those data TTL settings will override the same settings in core module.

recordDataTTL: ${SW_STORAGE_ES_RECORD_DATA_TTL:7} # Unit is day

otherMetricsDataTTL: ${SW_STORAGE_ES_OTHER_METRIC_DATA_TTL:45} # Unit is day

monthMetricsDataTTL: ${SW_STORAGE_ES_MONTH_METRIC_DATA_TTL:18} # Unit is month

bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:2000} # Execute the bulk every 2000 requests

bulkSize: ${SW_STORAGE_ES_BULK_SIZE:20} # flush the bulk every 20mb

flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10} # flush the bulk every 10 seconds whatever the number of requests

concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requests

metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}

segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}

        另外如果,想讓ES能同時被本地和遠端通路到,可以改一下ES的配置檔案,IP改為如下:

network.host: 0.0.0.0

      我專門寫了linux下的ES啟動腳本(腳本放在skywalking的bin目錄下,ES放在Skywalking的根目錄下),由于ES不能以root使用者啟動,是以腳本裡加了使用者的自動建立:

#!/bin/bash

check_user()

{

#判斷使用者是否存在passwd中

i=`cat /etc/passwd | cut -f1 -d':' | grep -w "$1" -c`

if [ $i -le 0 ]; then

echo "User $1 is not in the passwd"

return 0

#顯示使用者存在

echo "User $1 is in then use"

return 1

}

uname=elsearch

check_user $uname

if [ $? -eq 0 ]

then

#添加此使用者

sudo useradd $uname

passwd $uname --stdin "123456"

echo "user $uname add!!!"

Cur_Dir=$(cd "$(dirname "$0")"; pwd)

chown $uname:$uname -R $Cur_Dir/../elasticsearch

chmod -R 766 $Cur_Dir/../elasticsearch

chmod -R 777 $Cur_Dir/../elasticsearch/bin

su - $uname -c "nohup $Cur_Dir/../elasticsearch/bin/elasticsearch > $Cur_Dir/../elasticsearch/logs/output.log 2>&1 &"

echo "elasticsearch start success!"

          考慮到ES也是需要先啟動,確定端口監聽正常了,才能啟動oapService,是以我改造了skywalking自帶的啟動腳本,加了端口監聽判斷:  

check_port()

grep_port=`netstat -tlpn | grep "\b$1\b"`

echo "grep port is $grep_port"

if [ -n "$grep_port" ]

echo "port $port is in use"

echo "port is not established,please wait a moment......"

OAP_EXE=oapService.sh

WEBAPP_EXE=webappService.sh

elsearch_EXE=elasticsearchStart.sh

"$PRGDIR"/"$elsearch_EXE"

port=9200

echo "check $port"

for i in $(seq 1 20)

check_port $port

sleep 2s

break

"$PRGDIR"/"$OAP_EXE"

"$PRGDIR"/"$WEBAPP_EXE"

Windows下的腳本就簡單多了:

set OAP_PROCESS_TITLE=Skywalking-Elasticsearch

start "%OAP_PROCESS_TITLE%" %OAP_HOME%\elasticsearch\bin\elasticsearch.bat

而且windows下啟動ES很快,沒有端口啟動的延時時間,是以整個skywalking啟動腳本的改造量不大:

call "%~dp0"\elasticsearchUp.bat

call "%~dp0"\oapService.bat start

call "%~dp0"\webappService.bat start

以上的準備,就是為Skywalking應用ES存儲做好了準備,但是Elasticsearch本身也是存在寫入瓶頸的,也就是說ES也會崩潰,一但崩潰,就可能oapService關閉,或是導緻skywalking頁面大盤空白。

       我們可以做些調優,skywalking寫入ES的操作是使用了ES的批量寫入接口。我們可以調整這些批量的次元。盡量降低ES索引的寫入頻率,如:

bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:4000} # Execute the bulk every 2000 requests

bulkSize: ${SW_STORAGE_ES_BULK_SIZE:40} # flush the bulk every 20mb

flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:30} # flush the bulk every 10 seconds whatever the number of requests

concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:4} # the number of concurrent requests

metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:8000}

       調整bulkActions預設2000次請求批量寫入一次改到4000次;bulkSize批量重新整理從20M一次到40M一次;flushInterval每10秒重新整理一次堆改為每30秒重新整理;concurrentRequests查詢的最大數量由5000改為8000。這種配置調優确實生效了,重新開機服務後兩三天了都沒有出現過ES寫入阻塞的問題。不過這種設定隻是暫時的,你隻能期望流量不突發,或者應用不增加。一旦遇到突發流量和應用的增加,ES寫入瓶頸還是會凸顯出來。而且參數設定過大帶來了一個新的問題,就是資料寫入延時會比較大,一次服務互動發生的trace隔好久才能在skywalking頁面上查詢到。是以最終解決方案是優化ES的寫入性能,具體優化可以參考别人的文章:https://www.easyice.cn/archives/207

       另外作為開源化的平台,擴充性也是其中的優勢,本身ES就是分布式全文檢索架構,可以部署成高可用的叢集,另外Skyawalking也是分布式鍊路跟蹤系統,分布式既然是它應用的特性,那麼怎麼去建構叢集化的監控平台,就完全靠你自己的想象和發揮了。

       最後放一張我的Skywalking監控平台的監控效果圖(壓測過程中的應用監控),我可是鬥膽把人家的Logo都換了,但我可不會用在商用領域,隻是部門内部使用,友善其他人一眼認出這是個APM監控平台:

另外附上Skywalking各子產品完整的配置說明(為看不明白英文注釋的人準備):

 (1)Skywalking collector 配置

        OAP(Collector)鍊路資料歸集器,主要用于資料落地,大部分都會選擇 Elasticsearch 6,OAP配置檔案為 /opt/apache-skywalking-apm-6.2.0/config/application.yml,配置單點的 OAP(Collector)配置如下:

cluster:

# 單節點模式

standalone:

# zk用于管理collector叢集協作.

# zookeeper:

# 多個zk連接配接位址用逗号分隔.

# hostPort: localhost:2181

# sessionTimeout: 100000

# 分布式 kv 存儲設施,類似于zk,但沒有zk重型(除了etcd,consul、Nacos等都是類似功能)

# etcd:

# serviceName: ${SW_SERVICE_NAME:"SkyWalking_OAP_Cluster"}

# 多個節點用逗号分隔, 如: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379

# hostPort: ${SW_CLUSTER_ETCD_HOST_PORT:localhost:2379}

core:

default:

      # 混合角色:接收代理資料,1級聚合、2級聚合

# 接收者:接收代理資料,1級聚合點

# 聚合器:2級聚合點

      role: ${SW_CORE_ROLE:Mixed} # Mixed/Receiver/Aggregator

       # rest 服務位址和端口

      restHost: ${SW_CORE_REST_HOST:localhost}

      restPort: ${SW_CORE_REST_PORT:12800}

      restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}

      # gRPC 服務位址和端口

      gRPCHost: ${SW_CORE_GRPC_HOST:localhost}

      gRPCPort: ${SW_CORE_GRPC_PORT:11800}

      downsampling:

      - Hour

      - Day

      - Month

      # 設定度量資料的逾時。逾時過期後,度量資料将自動删除.

      # 機關分鐘

      recordDataTTL: ${SW_CORE_RECORD_DATA_TTL:90}

      minuteMetricsDataTTL: ${SW_CORE_MINUTE_METRIC_DATA_TTL:90}

      # 機關小時

      hourMetricsDataTTL: ${SW_CORE_HOUR_METRIC_DATA_TTL:36}

      # 機關天

      dayMetricsDataTTL: ${SW_CORE_DAY_METRIC_DATA_TTL:45}

      # 機關月

      monthMetricsDataTTL: ${SW_CORE_MONTH_METRIC_DATA_TTL:18}

      # elasticsearch 的叢集名稱

      nameSpace: ${SW_NAMESPACE:"local-ES"}

# elasticsearch 叢集節點的位址及端口

clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:192.168.2.10:9200}

# elasticsearch 的使用者名和密碼

user: ${SW_ES_USER:""}

password: ${SW_ES_PASSWORD:""}

# 設定 elasticsearch 索引分片數量

indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:2}

# 設定 elasticsearch 索引副本數

indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:0}

# 批量處理配置

# 每2000個請求執行一次批量

bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:2000}

# 每 20mb 重新整理一次記憶體塊

bulkSize: ${SW_STORAGE_ES_BULK_SIZE:20}

# 無論請求的數量如何,每10秒重新整理一次堆

flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:10}

# 并發請求的數量

concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2}

# elasticsearch 查詢的最大數量

metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}

# elasticsearch 查詢段最大數量

segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}

 (2)Skywalking webApp 配置

       Skywalking 的 WebApp 主要是用來展示落地的資料,是以隻需要配置 Web 的端口及擷取資料的 OAP(Collector)的IP和端口,webApp 配置檔案位址為  /opt/apache-skywalking-apm-6.2.0/webapp/webapp.yml 配置如下:

server:

port: 9000

collector:

path: /graphql

ribbon:

ReadTimeout: 10000

# 指向所有後端collector 的 restHost:restPort 配置,多個使用, 分隔

listOfServers: localhost:12800

security:

user:

# username

admin:

# password

password: admin

(3)Skywalking Agent 配置

       Skywalking 的 Agent 主要用于收集和發送資料到 OAP(Collector),是以需要進行配置 Skywalking OAP(Collector)的位址,Agent 的配置檔案位址為  /opt/apache-skywalking-apm-6.2.0/agent/config/agent.config,配置如下:

# 設定Agent命名空間,它用來隔離追蹤和監控資料,當兩個應用使用不同的名稱空間時,跨程序傳播鍊會中斷。

agent.namespace=${SW_AGENT_NAMESPACE:default-namespace}

# 設定服務名稱,會在 Skywalking UI 上顯示的名稱

agent.service_name=${SW_AGENT_NAME:Your_ApplicationName}

# 每 3秒采集的樣本跟蹤比例,如果是負數則表示 100%采集

agent.sample_n_per_3_secs=${SW_AGENT_SAMPLE:-1}

# 啟用 Debug ,如果為 true 則将把所有檢測到的類檔案儲存在"/debug"檔案夾中

# agent.is_open_debugging_class = ${SW_AGENT_OPEN_DEBUG:true}

# 後端的 collector 端口及位址

collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES:192.168.2.215:11800}

# 日志級别

logging.level=${SW_LOGGING_LEVEL:DEBUG}

下一篇: APM