使用 OSProfiler 对 OpenStack 进行性能测量
配置服务
如果要在 OpenStack 项目中使用 OSprofiler 进行性能跟踪,大部分项目已经帮我们
初始化了 OSprofiler, 只需要在配置文件中添加 [profiler]
配置项即可。
OSprofiler 支持使用多种 collector 存储数据,默认使用消息队列+Ceilometer(由oslo.messaging提供驱动)。
我这里使用 mongodb 作为 collection,原因只是我不喜欢 Ceilometer 和 Mongodb 更方便查询的GUI。
使用 mongodb 前需先安装 python mongodb 驱动 pip install pymongo
。
创建 mongodb 数据库,假设数据库 Host IP 为 172.16.140.116。
mkdir osprofiler_db && cd osprofiler_db
docker run \
-p 27017:27017 \
-v $pwd/data/db \
--name osprofiler_db \
-d mongo:latest
[profiler]
enabled = True
connection_string = mongodb://172.16.40.116:27017
# hmac_keys 将会被用作 `--osprofiler` 的参数,可以任意指定一串字符
hmac_keys = 123
# 控制跟踪的内容
trace_wsgi_transport = True
trace_message_store = True
trace_management_store = True
如果使用消息队列+Ceilometer,还需要配置Ceilometer,使其不会丢弃OSprofiler发送的消息。
[oslo_messaging_notifications]
topics = notifications, profiler
关于应该在哪些点进行跟踪,OSprofiler 的文档中建议:
-
所有的 HTTP 请求 - 发出了什么 HTTP 请求,请求时长(服务延迟),请求涉及项目
-
所有 RPC 请求 - 有助于理解某项目中不同服务请求时长,这对于发现项目性能瓶颈非常有用
-
所有 DB API 请求 - 某些情况下慢 DB 查询是性能瓶颈。DB 查询耗时是非常有用的数据。
-
所有驱动调用 - 在有 Nova, Cinder 或其他三方驱动情况下,跟踪驱动性能
-
所有 SQL 请求(默认关闭,因为会产生很多消息)
使用
假设想跟踪某个 API 请求,只需要在 openstack
命令添加 --osprofile hmac_key
,假设 Glance 已经配置好了
openstack image list --osprofile 123
命令运行完成后会在终端打印如下内容
Trace ID: 2902c7a3-ee18-4b08-aae7-4e34388f9352
Display trace with command:
osprofiler trace show --html 2902c7a3-ee18-4b08-aae7-4e34388f9352
接着使用 osprofiler
命令将报告以 html 格式打印出来。
# 记得指定后端
osprofiler trace show --html 2902c7a3-ee18-4b08-aae7-4e34388f9352 \
--connection-string "mongodb://172.16.140.116:27017" \
-o "report.html"
# 也可以输出 json 格式报告
osprofiler trace show --json 2902c7a3-ee18-4b08-aae7-4e34388f9352 \
--connection-string "mongodb://172.16.140.116:27017" \
-o "report.json"
使用浏览器打开 report.html 即可看到报告
添加自定义跟踪点
如果没有初始化 osprofiler,即使代码上打上跟踪点,osprofiler 也不会发送任何消息。如果在使用的项目中没有进行初始化,可以参考下面的方法进行初始化。
if CONF.profiler.enabled:
osprofiler_initializer.init_from_conf(
conf=CONF,
contex={},
project="cinder",
service=binary,
host=host
)
有 5 种方法在代码中打跟踪点
from osprofiler import profiler
# 手动设置开启和关闭
def some_func():
profiler.start("point_name", {"any_key": "with_any_value"})
# your code
profiler.stop({"any_info_about_point": "in_this_dict"})
# 使用装饰器
@profiler.trace("point_name",
info={"any_info_about_point": "in_this_dict"},
hide_args=False)
def some_func2(*args, **kwargs):
# 如果需要隐藏 profile 信息中的 args, 使用 hide_args=True
pass
# 使用上下文管理器
def some_func3():
with profiler.Trace("point_name", info={"any_key": "with_any_value"}):
# some code here
# 跟踪某个类方法
@profiler.trace_cls("point_name", info={}, hide_args=False,
trace_private=False)
class TracedClass(object):
def traced_method(self):
pass
# 对于 "_" 开头的方法,默认不会跟踪,若有必要可以使用 trace_private=True
def _traced_only_if_trace_private_true(self):
pass
# 添加元类
@six.add_metaclass(profiler.TracedMeta)
class RpcManagerClass(object):
__trace_args__ = {'name': 'rpc', 'info': None, 'hide_args': False, 'trace_private': False}
def my_method(self, some_args):
pass
def my_method2(self, some_arg1, some_arg2, kw=None, kw2=None):
pass
本作品采用《CC 协议》,转载必须注明作者和本文链接