zipkin微服務調用鏈分析(python)

一,概述

zipkin的作用

在微服務架構下,一個http請求從發出到響應,中間可能經過了N多服務的調用,或者N多邏輯操作,
如何監控某個服務,或者某個邏輯操作的執行情況,對分析耗時操作,性能瓶頸具有很大價值,
zipkin幫助我們實現了這一監控功能。

 

二、安裝zipkin

環境說明

操作系統:centos 7.6

ip:192.168.31.232

配置:2核4g

python版本:3.5.2

 

啓動zipkin

啓動方式有2種,一個是docker,一個jar包。任選其一即可。

本文采用jar包方式啓動

docker

docker run --name zipkin -d -p 9411:9411 openzipkin/zipkin

 

jar包

wget https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/2.12.9/zipkin-server-2.12.9-exec.jar
java -jar zipkin-server-2.12.9-exec.jar

 

訪問zipkin

http://192.168.31.232:9411

 

效果如下:

 

 

三、python實現zipkin

使用py_zipkin模塊來實現,這裏以flask項目來測試。

安裝模塊

pip3 install  py_zipkin pymysql flask

 

創建項目

新建demo.py

mkdir -p /data/flask_demo/
cd /data/flask_demo/
vim demo.py

內容如下:

import requests
from flask import Flask
from py_zipkin.zipkin import zipkin_span,create_http_headers_for_new_span
import time

app = Flask(__name__)

app.config.update({
    "ZIPKIN_HOST":"127.0.0.1",
    "ZIPKIN_PORT":"9411",
    "APP_PORT":5000,
    # any other app config-y things
})


def do_stuff():
    time.sleep(2)
    headers = create_http_headers_for_new_span()
    requests.get('http://localhost:6000/service1/', headers=headers)
    return 'OK'


def http_transport(encoded_span):
    # encoding prefix explained in https://github.com/Yelp/py_zipkin#transport
    #body = b"\x0c\x00\x00\x00\x01"+encoded_span
    body=encoded_span
    zipkin_url="http://127.0.0.1:9411/api/v1/spans"
    #zipkin_url = "http://{host}:{port}/api/v1/spans".format(
     #   host=app.config["ZIPKIN_HOST"], port=app.config["ZIPKIN_PORT"])
    headers = {"Content-Type": "application/x-thrift"}

    # You'd probably want to wrap this in a try/except in case POSTing fails
    r=requests.post(zipkin_url, data=body, headers=headers)
    print(type(encoded_span))
    print(encoded_span)
    print(body)
    print(r)
    print(r.content)


@app.route('/')
def index():
    with zipkin_span(
        service_name='webapp',
        span_name='index',
        transport_handler=http_transport,
        port=5000,
        sample_rate=100, #0.05, # Value between 0.0 and 100.0
    ):
        with zipkin_span(service_name='webapp', span_name='do_stuff'):
            do_stuff()
        time.sleep(1)
    return 'OK', 200

if __name__=='__main__':
    app.run(host="0.0.0.0",port=5000,debug=True)
View Code

 

新建server1.py

from flask import request
import requests
from flask import Flask
from py_zipkin.zipkin import zipkin_span,ZipkinAttrs
import time
import pymysql

app = Flask(__name__)
app.config.update({
    "ZIPKIN_HOST":"127.0.0.1",
    "ZIPKIN_PORT":"9411",
    "APP_PORT":5000,
    # any other app config-y things
})


def do_stuff():
    time.sleep(2)
    with zipkin_span(service_name='service1', span_name='service1_db_search'):
        db_search()
    return 'OK'


def db_search():
    # 打開數據庫連接
    db = pymysql.connect("127.0.0.1", "root", "123456", "mysql", charset='utf8')
    # 使用cursor()方法獲取操作遊標
    cursor = db.cursor()
    # 使用execute方法執行SQL語句
    cursor.execute("SELECT VERSION()")
    # 使用 fetchone() 方法獲取一條數據
    data = cursor.fetchone()
    print("Database version : %s " % data)
    # 關閉數據庫連接
    db.close()

def http_transport(encoded_span):
    # encoding prefix explained in https://github.com/Yelp/py_zipkin#transport
    #body = b"\x0c\x00\x00\x00\x01" + encoded_span
    body=encoded_span
    zipkin_url="http://127.0.0.1:9411/api/v1/spans"
    #zipkin_url = "http://{host}:{port}/api/v1/spans".format(
    #    host=app.config["ZIPKIN_HOST"], port=app.config["ZIPKIN_PORT"])
    headers = {"Content-Type": "application/x-thrift"}

    # You'd probably want to wrap this in a try/except in case POSTing fails
    requests.post(zipkin_url, data=body, headers=headers)


@app.route('/service1/')
def index():
    with zipkin_span(
        service_name='service1',
        zipkin_attrs=ZipkinAttrs(
            trace_id=request.headers['X-B3-TraceID'],
            span_id=request.headers['X-B3-SpanID'],
            parent_span_id=request.headers['X-B3-ParentSpanID'],
            flags=request.headers['X-B3-Flags'],
            is_sampled=request.headers['X-B3-Sampled'],
        ),
        span_name='index_service1',
        transport_handler=http_transport,
        port=6000,
        sample_rate=100, #0.05, # Value between 0.0 and 100.0
    ):
        with zipkin_span(service_name='service1', span_name='service1_do_stuff'):
            do_stuff()
    return 'OK', 200

if __name__=='__main__':
    app.run(host="0.0.0.0",port=6000,debug=True)
View Code

 

運行demo.py

python3 demo.py

 

運行server1.py

python3 server1.py

 

訪問5000端口

四、查看調用鏈

點擊查證,點擊下面的結果

 

 效果如下:

 

可以看到,有webapp和services兩個service,5個span標籤,可以清楚看到service和service,service和span,span和span之間的關係,和各span耗時情況。

 

點擊依賴,效果如下:

 

點擊webapp,效果如下:

 

 

五、api調用

官網api文檔:https://zipkin.io/zipkin-api/#/default/get_traces

 

這裏演示一下,調用2個api

services

返回與span終結點關聯的所有服務名稱的列表。

 

http://192.168.31.232:9411/api/v2/services

 效果如下:

 

 

 

traces

 調用此請求將檢索與以下篩選器匹配的跟蹤。

 

 http://192.168.31.232:9411/api/v2/traces

效果如下:

 

 這裏的tags,可以顯示錯誤信息。

 

有錯誤時,就是紅色的,點擊紅色區塊

 

 

就可以看到具體信息

這個錯誤信息表示,無法連接到mysql。因爲這臺機器,還沒有mysql服務。

 

爲了消除這個錯誤,可以再啓動一個mysql數據庫。

mkdir -p /data/mysql
docker pull mysql:5.7

docker run -itd -p 3306:3306 --name wiki-mysql -e MYSQL_ROOT_PASSWORD=123456 --restart=always --restart=on-failure:1 --oom-score-adj -1000 --privileged=true --log-opt max-size=10m --log-opt max-file=1 -v /data/mysql:/var/lib/mysql  mysql:5.7

 

重新啓動server1.py

再次訪問5000端口

再次查詢一次,就沒有紅色了

 

如果需要做報警,可以通過調用api,獲取到error信息,進行統一的郵件通知。

 

六、mysql的方式存儲

注意:zipkin的數據,默認是存在內存中的,如果重啓服務,會造成數據丟失。 

在現有數據庫基礎上,新建實例,實例名爲zipkin。

CREATE DATABASE zipkin DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

 

然後執行官網建庫腳本

https://github.com/openzipkin/zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql

 

執行sql之後,會建立3張表

 

這樣我們的數據庫就建好了。

 

執行

STORAGE_TYPE=mysql MYSQL_USER=root MYSQL_PASS=123456 MYSQL_HOST=127.0.0.1 MYSQL_TCP_PORT=3306 java -jar zipkin-server-2.12.9-exec.jar

這樣啓動zipkin,就自動連上mysql,並存儲數據了。

如圖,大功告成

 

 

注意,一般我們都在後臺運行zipkin,所以用nohup的方式啓動,命令如下

STORAGE_TYPE=mysql MYSQL_USER=root MYSQL_PASS=123456 MYSQL_HOST=127.0.0.1 MYSQL_TCP_PORT=3306 nohup java -jar zipkin-server-2.12.9-exec.jar &

 

 

本文參考鏈接:

https://www.cnblogs.com/shijingjing07/p/9340131.html

https://www.cnblogs.com/tseng-iOS/p/8005889.html

發佈了287 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章