34. 服务器管理Part 2: 服务器监控¶
34.1. Counter¶
iFun引擎在游戏服务器内通过Counter显示。利用它,可以直接创建外部监控工具。同时,iFun引擎还提供了可以运用counter监控多种信息的 iFun引擎dashboard 。(具体内容请参考 iFun引擎dashboard。 )
34.1.1. 计数器的读取和写入¶
34.1.1.2. 读取计数器¶
已创建好的计数器可在服务器内通过Integer、String、Double的形式读取。 读取外部计数器时,请参考 通过REST形式读取外部计数器 。
34.1.1.3. 计数器使用示例¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include <funapi.h>
void example(){
UpdateCounter("server", "item_count", 150);
UpdateCounter("server", "monster_count", "The number of monsters", 150);
IncreaseCounterBy("server", "item_count", 1);
DecreaseCounterBy("server", "item_count", 1);
int64_t item_count = ReadCounterAsInteger("server", "item_count");
BOOST_ASSERT(item_count == 150);
UpdateCounter("server", "connection_per_second", 77.7);
UpdateCounter("billing", "purchase_per_second", 7.1);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using funapi;
public void Example()
{
Counter.Update ("server", "item_count", 150);
UpdateCounter("server", "monster_count", "The number of monsters", 150);
Counter.Increase ("server", "item_count", 1);
Counter.Decrease ("server", "item_count", 1);
Int64 item_count = Counter.ReadInteger ("server", "item_count");
Counter.Update ("server", "connection_per_second", 77.7);
Counter.Update ("billing", "purchase_per_second", 7.1);
}
|
34.1.1.4. 通过REST形式读取外部计数器¶
前面定义的counter,可按如下方式访问。
-
GET
http://localhost:8014/v1/counters/
¶ 导入全部计数器category列表。
-
GET
http://localhost:8014/v1/counters/funapi/
¶ 显示作为已预约的计数器category的iFun引擎category内的计数器列表。
-
GET
http://localhost:8014/v1/counters/server/item_count/
¶ 读取程序员创建的server category内的
item_count
计数器值。上述示例中为150
。
-
GET
http://localhost:8014/v1/counters/billing/purchase_per_second/
¶ 读取程序员创建的billing category内的
perchase_per_second
计数器值。上述示例中为7.1
。
-
GET
http://localhost:8014/v1/counters/server/monster_count/description/
¶ 读取程序员创建的server category内的
monster_count
计数器值。上述示例中为 “The number of monsters” 。Tip
如果为Counter添加注释,则可在与外部系统联动时向外部作业人员提供更加明确的涵义。
34.1.2. 监测计数器变化¶
对于 Integer
和 Double
类型的计数器,当计数器的值为特定值以上时,可以输出日志。
利用该功能,有助于监测游戏内金币的急剧变化等。
下面的示例中通过Counter计算玩家每小时收集的金币量,超过10万时,会显示提示消息。
34.1.2.1. 计数器变化感测示例¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | void OnResetGoldCounterTimerExpired(const Timer::Id &, const WallClock::Value &) {
UpdateCounter("game", "gold_per_hour", 0);
}
void Install() {
UpdateCounter("game", "gold_per_hour", 0);
MonitorCounter("game", "gold_per_hour", 100000);
Timer::ExpireRepeatedly(WallClock::FromSec(3600), OnResetGoldCounterTimerExpired);
}
// Assume this function is called when user pick gold.
void PickGold(int64_t gold) {
IncreaseCounterBy("game", "gold_per_hour", gold);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void OnResetGoldCounterTimerExpired(UInt64 timer_id, DateTime clock)
{
Counter.Update ("game", "gold_per_hour", 0);
}
void Install()
{
Counter.Update ("game", "gold_per_hour", 0);
Counter.Monitor ("game", "gold_per_hour", 100000);
Timer.ExpireRepeatedly (WallClock.FromSec (3600), OnResetGoldCounterTimerExpired);
}
// Assume this function is called when user pick gold.
void PickGold(UInt64 gold)
{
Counter.Increase ("game", "gold_per_hour", gold);
}
|
Note
如示例所示,为了注册监控器,须要调用 UpdateCounter()
、
IncreaseCounterBy()
、 DecreaseCounterBy()
函数等,提前注册好计数器。
现在每小时金币量超出10万金币时,就会显示如下日志。
W0818 11:03:06.520730 18324 counter.cc:160] The 'gold_per_hour of game' counter exceeded threshold: value=123456, threshold=100000
34.1.2.2. 输出变化感测日志¶
为防止生成过多的日志,每次输出的日志不会超出已在 MonitorCounter()
函数中输入的 threshold
值。
但会以已在 计数器的设置参数 的 counter_monitoring_interval_in_sec
输入的秒数为单位,定期确认计数器值,输出日志。
34.1.3. 默认提供的计数器列表¶
以下是引擎默认提供的计数器列表。
34.1.3.1. process¶
用于查询iFun引擎正在运行的进程信息的计数器。
Counter名称
说明
vsz
进程占用的虚拟内存大小。
cpu
进程的cpu使用率。
nivcsw
上下文切换之前任务未结束的次数。
nswap
当前不使用的字段。
oublock
文件系统已输出数。
minflt
在没有I/O的情况下出现的缺页故障数。
idrss
未共享的rss大小。
isrss
未共享的栈内存大小。
ixrss
共享的rss内存大小。
nsignals
收到响应的信号数。
majflt
因I/O而发生的缺页故障数。
maxrss
曾使用的rss最大值。
msgsnd
IPC消息传输数。
msgrcv
IPC消息响应数。
nvcsw
上下文切换之前任务结束的次数。
stime
进程以Kernel模式运行的总时间。
updated
最近一次更新的UTC时间。
utime
进程以用户模式运行的总时间。
inblock
文件系统已输入数。
refresh_interval
计数器更新周期(秒)。
34.1.3.2. os¶
查询服务器os信息的计数器。
Counter名称
说明
procs
正在运行的所有进程数。
freeswap
可使用的内存大小(byte)。
bufferram
作为缓冲区使用的内存大小(byte)。
load15
15分钟内的load average。
totalswap
全部内存大小(byte)。
load5
5分钟内的load average。
load1
1分钟内的load average。
updated
最近一次更新的UTC时间。
uptime
服务器启动时间与当前时间的间隔(秒)。
freeram
空闲RAM大小(byte)。
cpus
cpu核数。
totalram
全部RAM大小(byte)。
refresh_interval
计数器更新周期(秒)。
sharedram
全部共享内存大小(byte)。
type
os类型种类。
34.1.3.3. funapi¶
查询服务器的引擎信息。
Counter名称
说明
concurrent_user
当前访问服务器的用户数。须运用
AccountManager
做登录处理。具体内容请参考 查找客户端访问的服务器 。sessions
当前访问服务器的会话数。
object
查询服务器中缓存的对象数、待处理的读取和写入Query数。
object_database_stat
各数据库对象相关Query的处理时间统计。具体内容请参考 (高级) ORM 性能分析 。
rpc_stat
RPC性能统计。
zookeeper_stat
为了共享对象而使用的
Zookeeper
的处理时间统计。具体内容请参考 Zookeeper处理的性能分析 。event/performance/queue
查询服务器的事件流入量、处理量,以及正在等待的事件数等。
event/profiling/all
各事件的处理时间统计。具体内容请参考 事件性能分析: 详细信息 。
event/profiling/summary
所有事件的处理时间的统计。具体内容请参考 事件性能分析: 概要信息 。
event/profiling/reset
对事件性能解析进行重置。
event/profiling/outstanding
正在处理中的事件统计。
34.1.3.4. funapi_object_model¶
按model查询服务器中缓存的各对象数。
34.1.4. (高级)Callback型计数器¶
除了单纯注册并返回数字值以外,有时也须要为了计算计数器的值 而进行追加运算,或返回多个值。
例如,在须要返回平均值的情况,通常先在内部计算所有值的和与个数, 当需要平均值时,会返回用和除以个数后得到的值。
为进行这种运算,可以在counter中注册callback。
34.1.4.1. Callback型计数器使用示例¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <funapi.h>
http::StatusCode OnAverageQueried(
const string &counter_group, // "server" when called
const string &counter_name, // "average_users_per_room" when called.
Json *ret) {
if (total_rooms == 0) {
return http::kNoContent;
}
double average = total_users / total_rooms;
ret->SetDouble(average);
return http::kOk;
}
void example() {
RegisterCallableCounter(
"server",
"average_users_per_room",
"Returns the average number of users per game room",
OnAverageQueried);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using funapi;
funapi.http.StatusCode OnAverageQueried(
string counter_group, // "server" when called
string counter_name, // "average_users_per_room" when called
JObject ret)
{
if (total_rooms == 0) {
return funapi.http.StatusCode.kNoContent;
}
double average = total_users / total_rooms;
ret->SetDouble(average);
return funapi.http.StatusCode.kOk;
}
void Example()
{
Counter.RegisterCallableCounter (
"server",
"average_users_per_room",
"Returns the average number of users per game room",
OnAverageQueried);
}
|
-
GET
http://localhost:8014/v1/counters/server/average_users_per_room/
¶ 调用该API后,将调用
OnAverageQueried()
,计算平均值后返回。
34.1.5. 计数器的设置参数¶
counter_flush_interval_in_sec: 定期更新外部显示的counter值时的时间间隔,单位为秒(type=uint64, default=0)
几乎不需要直接更改设置的参数
counter_monitoring_interval_in_sec: 对除了向外部发送的值以外的所有值进行监控的时间间隔,单位为秒(type=uint64, default=30)
warning_threshold_event_queue_length: 监控计数器时,若事件队列比该值长,将显示警告框(type=uint64, default=3000)
warning_threshold_outstanding_fetch_query: 监控计数器时,若DB读取队列比该值长,将显示警告框(type=uint64, default=3000)
warning_threshold_outstanding_update_query: 监控计数器时,若DB写入队列比该值长,将显示警告框(type=uint64, default=3000)
warning_threshold_slow_query_in_sec: 카운터 모니터링 시 DB 읽기 또는 쓰기에 소요되는 시간(단위: 초)이 기준 값보다 길어질 때 경고 메세지를 출력함(type=uint64, default=1)
warning_threshold_slow_distribution_in_sec: 카운터 모니터링 시 분산 처리에 사용되는 Zookeeper/Redis 처리 시간(단위: 초)이 기준 값보다 길어질 때 경고 메세지를 출력함(type=uint64, default=3)
34.2. iFun引擎dashboard¶
iFun引擎提供了可以便利监控游戏服务器的单独仪表盘(dashboard)程序。 该仪表盘程序通过 Counter 实现。 具体内容请参考 iFun引擎dashboard手册
iFun引擎仪表盘提供以下几种代表性的功能。