成都网站建设设计

将想法与焦点和您一起共享

cephmgr命令卡住-创新互联

1  问题描述

创新互联建站是一家集网站建设,嘉禾企业网站建设,嘉禾品牌网站建设,网站定制,嘉禾网站建设报价,网络营销,网络优化,嘉禾网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

 在ceph12和ceph14.2.8使用过程中遇到,当osd数量很多时(1000多个),pg需要设置很多(5、6万)时,ceph balancer status  或  ceph osd status等mgr命令会卡住很长时间才返回,其它mon等命令没问题。

2  问题排查

 卡住的都是mgr相关命令,因此推测是mgr进程问题。

 排查是osd多,还是pg多导致,这个很容易操作不详细介绍,通过实验是pg多导致的。下图是我的测试环境的ceph: 

 使用top -H命令可以发现mgr-fin线程cpu使用率经常达到100%。

使用ceph daemon mgr.ceph-212 perf dump查看mgr统计信息      

mgr-fin线程cpu使用率经常达到100%,finisher队列数据量很大,队列又是mgr-fin一个线程在处理,mgr命令发给mgr后就进入finisher队列排队处理,导致mgr命令卡住。

Mgr参数说明:

  "mgr_stats_period": "5"    默认为5秒,每5秒所有osd、mds和其它mgr会给主mgr发送一个MSG_MGR_REPORT消息,所有osd给主mgr发送MSG_PGSTATS消息

"mgr_tick_period": "2"     mgr每隔2秒给mon发送beacon

“mgr_mon_messages”     mgr-mon限流大值,默认为128

Mon参数说明:

  "mon_mgr_digest_period": "5"  默认为5秒,每隔5秒,mon会给主mgr发送MSG_MGR_DIGEST

3  mgr介绍

 mgr模块分担和扩展monitor的部分功能,减轻monitor的负担。入口在src/ceph_mgr.cc的main函数。

 所有mgr服务启动时身份都是standby(初始化一个MgrStandby类对象),初始化一个monitor的客户端monc(MonClient类),调用monc.sub_want函数向monitor请求mgrmap(MSG_MGR_MAP消息)及相关msg。

 在MgrStandby::ms_dispatch函数中处理收到的消息,既MgrStandby::handle_mgr_map函数处理MSG_MGR_MAP消息,发现自己在mgrmap为active时,会初始化mgr主服务进程,然后调用Mgr::background_init -->finisher.start()启动Finisher的线程 -->调用finisher.queue向Finisher的队列里添加任务,此任务为Mgr::init(),MgrStandby::send_beacon()。

Mgr::init函数

DaemonServer::init 初始化daemonServer:

初始化了一个mgr类型的Messenger msgr,监听有关mgr消息,收到消息后通过DaemonServer::ms_dispatch处理此消息,包括MSG_PGSTATS、MSG_MGR_REPORT、MSG_MGR_OPEN、MSG_MGR_CLOSE和MSG_COMMAND。

 Mgr::load_all_metadata

向monitor节点发请求分别获取mds、osd和mon的元数据,然后根据这些元数据信息生成3个(分别记录mds、osd和mon的元数据)DaemonState的share_ptr添加到daemon_state中。

 通过monc->sub_want函数向monitor发消息,分别获取log-info、mgrdigest、fsmap  、servicemap和osdmap。Mgr::ms_dispatch函数处理收到的消息,包括MSG_MGR_DIGEST、CEPH_MSG_MON_MAP、CEPH_MSG_FS_MAP、CEPH_MSG_OSD_MAP、MSG_SERVICE_MAP和MSG_LOG。

 

py_module_registry->active_start:

  这个py_module_registry(PyModuleRegistry类对象)是在mgr服务启动时初始化一个MgrStandby类对象时初始化,然后初始化Mgr类时传进来。MgrStandby::init时调用py_module_registry.init函数(既PyModuleRegistry类的init)加载pyModule:

参数mgr_module_path的值(默认为/usr/share/ceph/mgr/)下所有目录中下面有文件module.py的目录的名字为pyModule的名字(源码中是src/pybing/mgr下的python模块)。为所有的这些pyModule生成类PyModule对象,调用mod->load加载modules,然后添加进modules中。

active_modules.reset(new ActivePyModules(...)) 重新初始化active_modules。

for (const auto &i : modules){

active_modules->start_one(i.second)

}

ActivePyModules::start_one:

modules[name].reset(new ActivePyModule(py_module, clog));

finisher.queue(new FunctionContext([this, active_module, name](int) {

  int r = active_module->load(this);

  active_module->thread.create(active_module->get_thread_name());

 }

处理MSG_MGR_DIGEST消息: (默认每隔5秒,mon会给主mgr发送MSG_MGR_DIGEST)

  Mgr::ms_dispatch函数里检查到消息类型是MSG_MGR_DIGEST时调用Mgr::handle_mgr_digest函数

cluster_state.load_digest(m)       从m中提取数cluster_state.health_json,

cluster_state.mon_status_json。

py_module_registry->notify_all("mon_status", "");

py_module_registry->notify_all("health", "");

py_module_registry->notify_all("pg_summary", "");

PyModuleRegistry::notify_all(const std::string ¬ify_type, const std::string ¬ify_id)

active_modules->notify_all函数 既ActivePyModules::notify_all

遍历modules中的ActivePyModule,创建一个任务添加到finisher队列里,此任务调

用ActivePyModule::notify:

  调用pyModule的(源码中是src/pybing/mgr下的python模块下的module.py)的

  notify函数

src/pybing/mgr/progress/module.py中的notify函数

  当notify_type 是"osd_map"时,调用self._osdmap_changed检查是否有osd out了或有新osd加入。

旧的osd out,就调用self._osd_out查找被out的这个osd影响的pg,然后生成一个PgRecoveryEvent对象ev,self._events[ev.id] = ev

新osd加入,就调用self._osd_in检查self._events中是否有PgRecoveryEvent事件ev并且加入的osd在ev.evacuating_osds中,如果有,则结束此ev。

 当notify_type 是"pg_summary"时:

  data = self.get("pg_dump") 调用ceph_state_get函数 -->self->py_modules->get_python("pg_dump"),即ActivePyModules::get_python获取pg_map格式化后返回,当pg数量很多时,pg_map就会很大,获取pg_map并格式化比较耗时(当pg数量达到6万多时,我统计了下可达到5秒)。但是下面只有当字典self._events不为空时才有可能处理获取的pg_map数据,因此这一步很多时候是多余的,因此可以先判断self._events不为空时才获取pg_map,可以减轻mgr进程的压力。默认每隔5秒,mon会给主mgr发送MSG_MGR_DIGEST,mgr收到后,会执行到这里处理,因此这里很可能就是pg多时,mgr卡住的一个原因。

//这里的self._events中有两类event:PgRecoveryEvent和RemoteEvent。PgRecoveryEvent是正在进行的pg recovery事件(由前面的self._osd_out创建),RemoteEvent由update函数创建

for ev_id, ev in self._events.items(): //更新self._events

if isinstance(ev, PgRecoveryEvent):

ev.pg_update(data, self.log)

self.maybe_complete(ev)

src/pybing/mgr/progress/module.py中的update函数

 如果self._events中有ev_id,则ev = self._events[ev_id],否则ev =RemoteEvent(ev_id, ev_msg, refs),self._events[ev_id] = ev。

ev.set_progress(ev_progress)

ev._refresh()

4  解决问题

  根据上面mgr的介绍和分析,pg多时,mgr卡住的一个原因可能是因为src/pybing/mgr/progress/module.py中的notify函数处理"pg_summary"时没有检查self._events是否为空,就调用self.get("pg_dump")获取并格式化pg_map,比较耗时,finisher队列是mgr-fin一个线程在处理,这里耗时太多,就导致finisher队列里数据来不及处理导致堆积。

因此可以在调用self.get("pg_dump")时,先检查self._events是否为空,如果为空就直接退出notify函数。

  经过验证,加入此判断后,重启mgr,运行一段时间后,使用ceph daemon mgr.ceph-212 perf dump查看mgr统计信息:      

  查看mgr命令耗时:

可知,finisher队列数据量很小,mgr命令也可以很快返回,问题解决。

当然也可以直接升级ceph到14.2.22。

  

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前名称:cephmgr命令卡住-创新互联
分享路径:http://chengdu.cdxwcx.cn/article/dcjcoj.html