日志与追踪:深入理解系统行为
1. 为 SimpleBank 设置日志基础设施
1.1 生成日志数据
要生成日志数据,只需向网关服务创建一个出售请求。可以通过向网关发出 POST 请求来实现,以下是使用 curl 发出请求的示例:
chapter-12$ curl -X POST http://localhost:5001/shares/sell \
-H 'cache-control: no-cache' \
-H 'content-type: application/json'
chapter-12$ {"ok": "sell order e11f4713-8bd8-4882-b645-55f96d220e44 placed"}
1.2 使用 Kibana 探索日志数据
收集到日志数据后,可使用 Kibana 进行探索。点击 Kibana 网页仪表盘左侧的 “Discover” 部分,会进入一个可执行搜索的页面。在搜索框中,插入作为出售订单响应收到的请求 UUID。例如,在上述示例中,使用 e11f4713-8bd8-4882-b645-55f96d220e44 作为搜索参数。
1.3 在海量数据中查找信息
在代码示例中,有五个独立的服务协作,允许 SimpleBank 用户出售股票。所有服务都记录其操作,并使用请求 UUID 作为唯一标识符,以便聚合所有与正在处理的出售订单相关的日志消息。当使用请求 ID 作为搜索参数时,Kibana 会过滤日志数据,可获得 11 个匹配项,从而跟踪请求在不同服务中的执行情况。Kibana 还允许使用复杂查询来揭示更多信息,例如按服务过滤、按时间排序,甚至使用日志数据(如日志条目中的执行时间)创建仪表板来跟踪性能。
1.4 记录正确的信息
在能够收集和存储日志后,需要注意通过日志发送的信息。像密码、信用卡号、身份证号和潜在敏感的个人数据等发送的信息将被存储,任何能够使用日志基础设施的人都可以访问这些信息。即使是自己托管和控制日志基础设施,也需谨慎。如果使用第三方提供商,则需要格外注意这些细节。因为很难只删除已发送的部分数据,大多数情况下,如果要删除特定内容,意味着删除给定时间段内的所有日志数据。
数据隐私是当前的热门话题,随着欧盟通用数据保护条例 (GDPR) 的生效,在考虑记录哪些数据以及如何记录时需要格外小心。Fluentd 和 Elasticsearch 允许对数据应用过滤,以便对收到的数据中的任何敏感字段进行掩码、加密或删除。一般规则是尽可能少地记录信息,避免在日志中记录任何个人数据,并在任何更改进入生产环境之前仔细审查记录的内容。
2. 服务间的追踪交互
2.1 OpenTracing API
OpenTracing API 是用于分布式追踪的与供应商无关的开放标准。许多分布式追踪系统(如 Dapper、Zipkin、HTrace、X-Trace)提供追踪功能,但使用不兼容的 API。选择其中一个系统通常意味着将可能使用不同编程语言的系统紧密耦合到单一解决方案中。OpenTracing 倡议的目的是提供一组约定和标准 API 来收集追踪信息。多个语言和框架都有可用的库。可以在 http://mng.bz/Gvr3 找到一些受支持的追踪器系统。
2.2 关联请求:追踪和跨度
追踪是一个或多个跨度的有向无环图 (DAG),这些跨度的边称为引用。追踪用于聚合和关联系统中的执行流程。为了实现这一点,需要传播一些信息。追踪捕获整个流程。
每个跨度包含以下信息:
- 操作名称
- 开始和结束时间戳
- 零个或多个跨度标签(键值对)
- 零个或多个跨度日志(带有时间戳的键值对)
- 跨度上下文
- 对零个或多个跨度的引用(通过跨度上下文)
跨度上下文包含引用不同跨度所需的数据,无论是本地还是跨服务边界。
2.3 在服务中设置追踪
2.3.1 添加 Jaeger 到 docker-compose.yml 文件
为了能够显示追踪信息并关联不同服务之间的请求,需要设置一个追踪收集器和 UI,并在服务中包含一些库并进行设置。以 SimpleBank 的配置文件和设置服务为例,以下是将 Jaeger 添加到 docker-compose.yml 文件的示例:
(…)
jaeger:
container_name: jaeger
image: jaegertracing/all-in-one:latest
ports:
- 5775:5775/udp
- 6831:6831/udp
- 6832:6832/udp
- 5778:5778
- 16686:16686
- 14268:14268
- 9411:9411
environment:
COLLECTOR_ZIPKIN_HTTP_PORT: "9411"
2.3.2 添加追踪库
在设置和配置文件服务中添加所需的库,并初始化追踪器。以下是通过 requirements.txt 文件添加追踪库的示例:
Flask==0.12.0
requests==2.18.4
jaeger-client==3.7.1
opentracing>=1.2,<2
opentracing_instrumentation>=2.2,<3
2.3.3 初始化追踪器
为了方便初始化追踪器,可以创建一个模块提供初始化函数,以下是 lib/tracing.py 的示例:
import logging
from jaeger_client import Config
def init_tracer(service):
logging.getLogger('').handlers = []
logging.basicConfig(format='%(message)s', level=logging.DEBUG)
config = Config(
config={
'sampler': {
'type': 'const',
'param': 1,
},
'local_agent': {
'reporting_host': "jaeger",
'reporting_port': 5775,
},
'logging': True,
'reporter_batch_size': 1,
},
service_name=service,
)
return config.initialize_tracer()
2.3.4 配置文件服务代码
以下是配置文件服务的代码示例,设置了外部 HTTP 服务和设置服务的跨度:
from urlparse import urljoin
import opentracing
import requests
from flask import Flask, jsonify, request
from opentracing.ext import tags
from opentracing.propagation import Format
from opentracing_instrumentation.request_context import get_current_span
from opentracing_instrumentation.request_context import span_in_context
from lib.tracing import init_tracer
app = Flask(__name__)
tracer = init_tracer('simplebank-profile')
@app.route('/profile/<uuid:uuid>')
def profile(uuid):
with tracer.start_span('settings') as span:
span.set_tag('uuid', uuid)
with span_in_context(span):
ip = get_ip(uuid)
settings = get_user_settings(uuid)
return jsonify({'ip': ip, 'settings': settings})
def get_ip(uuid):
with tracer.start_span('get_ip', child_of=get_current_span()) as span:
span.set_tag('uuid', uuid)
with span_in_context(span):
jsontest_url = "http://ip.jsontest.com/"
r = requests.get(jsontest_url)
return r.json()
def get_user_settings(uuid):
settings_url = urljoin("http://settings:5000/settings/", "{}".format(uuid))
span = get_current_span()
span.set_tag(tags.HTTP_METHOD, 'GET')
span.set_tag(tags.HTTP_URL, settings_url)
span.set_tag(tags.SPAN_KIND, tags.SPAN_KIND_RPC_CLIENT)
span.set_tag('uuid', uuid)
headers = {}
tracer.inject(span, Format.HTTP_HEADERS, headers)
r = requests.get(settings_url, headers=headers)
return r.json()
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
2.3.5 设置服务代码
以下是设置服务的代码示例,使用传入的父跨度:
import time
from random import randint
import requests
from flask import Flask, jsonify, request
from opentracing.ext import tags
from opentracing.propagation import Format
from opentracing_instrumentation.request_context import get_current_span
from opentracing_instrumentation.request_context import span_in_context
from lib.tracing import init_tracer
app = Flask(__name__)
tracer = init_tracer('simplebank-settings')
@app.route('/settings/<uuid:uuid>')
def settings(uuid):
span_ctx = tracer.extract(Format.HTTP_HEADERS, request.headers)
span_tags = {tags.SPAN_KIND: tags.SPAN_KIND_RPC_SERVER, 'uuid': uuid}
with tracer.start_span('settings', child_of=span_ctx, tags=span_tags):
time.sleep(randint(0, 2))
return jsonify({'settings': {'name': 'demo user', 'uuid': uuid}})
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
3. 可视化追踪信息
3.1 触发追踪收集
完成所有设置后,只需向 SimpleBank 配置文件端点发出请求即可开始收集追踪信息。可以使用命令行或浏览器。使用命令行访问追踪信息时,可以使用 curl 发出以下请求:
$ curl http://localhost:5007/profile/26bc34c2-5959-4679-9d4d-491be0f3c0c0
{
"ip": {
"ip": "178.166.53.17"
},
"settings": {
"settings": {
"name": "demo user",
"uuid": "26bc34c2-5959-4679-9d4d-491be0f3c0c0"
}
}
}
当访问配置文件端点时,发生的事情如下:
1. 配置文件服务创建一个跨度 A。
2. 配置文件服务联系外部服务获取 IP,将其封装在一个新的跨度 B 下。
3. 配置文件服务联系内部 SimpleBank 设置服务以获取用户信息,在一个新的跨度 C 下,并将父跨度的上下文传递给下游服务。
4. 两个服务将跨度信息传达给 Jaeger。
3.2 访问 Jaeger UI 可视化追踪
要可视化追踪信息,需要访问运行在端口 16686 的 Jaeger UI。在 “Service” 部分,可以看到三个有追踪信息的服务:两个 SimpleBank 服务和一个名为 jaeger-query 的服务。 jaeger-query 收集 Jaeger 内部追踪信息,对我们用处不大。我们感兴趣的是另外两个服务: simplebank-profile 和 simplebank-settings 。选择 simplebank-profile 并点击底部的 “Find Traces”,可以看到配置文件服务的追踪信息。
页面列出了六个追踪,所有追踪在两个服务中有三个跨度。这意味着可以收集到两个内部服务之间协作的信息,并获得执行的时间信息。通过查看详细视图,可以看到配置文件服务调用的不同步骤的时间线,包括整体执行时间、每个子操作的发生时间和持续时间。这些信息对于了解分布式系统中正在发生的事情非常有价值,可以可视化请求在不同服务中的流动,并知道每个操作完成所需的时间,从而识别潜在的瓶颈并进行改进。
此外,还可以使用 Jaeger 了解系统中不同组件之间的关系。点击顶部导航菜单栏中的 “Dependencies” 链接,然后在出现的页面中选择 “DAG (direct acyclic graph)” 标签,可以访问服务依赖视图。
4. 总结
- 可以使用 Elasticsearch、Kibana 和 Fluentd 设置日志基础设施,使用 Jaeger 设置分布式追踪。
- 日志基础设施可以生成、转发和存储索引日志数据,允许搜索和关联请求。
- 分布式追踪允许跟踪请求在不同微服务中的执行过程。
- 结合指标收集,追踪可以更好地理解系统的行为,识别潜在问题,并随时对系统进行审计。
通过日志和追踪,我们可以深入了解系统的行为和性能,为系统的优化和维护提供有力支持。
流程图展示
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(生成日志数据):::process --> B(使用 Kibana 探索日志):::process
B --> C(关联请求追踪):::process
C --> D(设置服务追踪):::process
D --> E(可视化追踪信息):::process
表格总结
| 步骤 | 描述 |
|---|---|
| 生成日志数据 | 向网关服务发出 POST 请求生成日志 |
| 使用 Kibana 探索 | 用请求 UUID 在 Kibana 搜索日志 |
| 关联请求追踪 | 用 OpenTracing API 关联请求 |
| 设置服务追踪 | 在服务中添加库和配置追踪 |
| 可视化追踪信息 | 访问 Jaeger UI 查看追踪信息 |
5. 日志与追踪的操作要点回顾
为了更清晰地理解和操作日志与追踪相关内容,下面对关键步骤进行详细回顾:
5.1 日志数据生成与探索
| 操作步骤 | 具体内容 |
|---|---|
| 生成日志数据 | 向网关服务发出 POST 请求,如使用 curl -X POST http://localhost:5001/shares/sell -H 'cache-control: no-cache' -H 'content-type: application/json' |
| 探索日志数据 | 点击 Kibana 网页仪表盘左侧的 “Discover” 部分,在搜索框插入请求 UUID 进行搜索 |
5.2 服务追踪设置
| 操作步骤 | 具体内容 |
|---|---|
| 添加 Jaeger 到 docker-compose.yml | 在文件中添加 Jaeger 相关配置,指定端口和环境变量 |
| 添加追踪库 | 在 requirements.txt 文件中添加 Flask 、 requests 、 jaeger-client 等库 |
| 初始化追踪器 | 创建 lib/tracing.py 模块,定义 init_tracer 函数 |
| 配置服务代码 | 在配置文件服务和设置服务中编写代码,设置跨度并传递上下文 |
6. 日志与追踪的实际应用场景
日志与追踪在实际应用中有广泛的场景,以下是一些常见的例子:
6.1 性能优化
通过追踪请求在不同服务中的执行时间,可以找出性能瓶颈。例如,如果发现某个跨度的执行时间过长,可以针对性地对该服务进行优化,如优化算法、增加资源等。
6.2 故障排查
当系统出现故障时,日志和追踪信息可以帮助快速定位问题。通过查看日志中的错误信息和追踪中的执行流程,可以确定故障发生的位置和原因。
6.3 安全审计
日志记录了系统的操作信息,可以用于安全审计。例如,检查是否有异常的登录行为、敏感数据的访问等。
7. 未来发展趋势
随着技术的不断发展,日志与追踪领域也在不断演进。以下是一些未来可能的发展趋势:
7.1 智能化分析
未来的日志与追踪系统可能会具备更强大的智能化分析能力,能够自动识别异常模式、预测潜在问题,并提供相应的解决方案。
7.2 与云原生技术的融合
随着云原生技术的普及,日志与追踪系统将更好地与容器、编排工具等集成,提供更全面的系统监控和管理。
7.3 多模态数据融合
除了日志和追踪数据,未来可能会融合更多类型的数据,如指标数据、事件数据等,提供更全面的系统视图。
8. 总结与建议
通过本文的介绍,我们了解了日志与追踪在系统监控和管理中的重要性,以及如何为 SimpleBank 设置日志基础设施和分布式追踪系统。以下是一些总结和建议:
- 合理记录日志 :避免记录敏感信息,遵循数据隐私法规,确保日志数据的安全性。
- 选择合适的工具 :根据系统的需求和规模,选择合适的日志和追踪工具,如 Elasticsearch、Kibana、Jaeger 等。
- 持续优化 :定期分析日志和追踪数据,不断优化系统性能和可靠性。
通过以上的操作和实践,我们可以更好地利用日志与追踪技术,深入理解系统行为,为系统的稳定运行和优化提供有力支持。
流程图展示
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
A(性能优化):::process --> B(故障排查):::process
B --> C(安全审计):::process
C --> D(智能化分析):::process
D --> E(与云原生融合):::process
E --> F(多模态数据融合):::process
表格总结
| 发展趋势 | 描述 |
|---|---|
| 智能化分析 | 自动识别异常模式、预测潜在问题 |
| 与云原生技术融合 | 更好地与容器、编排工具集成 |
| 多模态数据融合 | 融合日志、指标、事件等多类型数据 |
超级会员免费看

被折叠的 条评论
为什么被折叠?



