Erlang通用模板接入文档
<p>[TOC]</p>
<p>Tips:
公网consul注册地址:124.222.148.13:8500
公网pushgateway注册地址:124.222.148.13:9091
内网consul注册地址:192.168.1.96:8500
内网pushgateway注册地址:192.168.1.96:9091</p>
<h1>一、背景</h1>
<p>为了更好的对各项目组游戏进行服务监控,运维方目前已配合部分工作室负责人一同做出对erlang服务监控两种方案。目前都已测试完毕并且正在稳定运行,在监控中,通过对游戏平台以及服务端序列号进行筛选,可以很清楚的看见游戏erlang服务各节点状态、不仅限于内存使用信息、节点基础信息、系统基础信息等监控数据。因此,想把这两套监控方案分享到所有项目组进行参考使用,二选其一即可。</p>
<h1>二、方案一</h1>
<h2>【2.1】整体架构图</h2>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=51c52cda24c43861600086b5cc8849cd&amp;file=file.png" alt="" /></p>
<p><strong>流程简介:</strong></p>
<ul>
<li>游戏节点内启动<code>prom_mgr</code>进程,只负责定时进⾏数据采集并上报到gateway服务(类似⽇志上报)。promethes⾃动定时向gateway中间件拉取数据,拉取间隔1m。</li>
<li>在注册服务时只需要pushgateway对注册方开放9091端口,注册方不需要暴露游戏服的端口。</li>
</ul>
<h2>【2.2】代码清单</h2>
<ul>
<li><code>prom_render.erl</code> :改造⾃开源第三⽅库https://github.com/deadtrickster/prometheus.erl,抽 离数据格式化的关键接⼝,⽐源库更轻量。 </li>
<li><code>prom_mgr.erl</code>:定时进⾏指标收集及指标上报,收集的指标依赖于 Collector 模块的指标定义。 </li>
<li><code>prom_vm.erl</code>:数据收集器,⽬前实现了节点内部分数据收集,可增加对指定进程的监控(cpu、 内存、队列)。 </li>
<li><code>prom.hrl</code>:头⽂件。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=2ab20824590620c62d5fa4d776eb0a8d&amp;file=file.png" alt="" /></li>
</ul>
<p><strong>注:</strong>可通过“普罗米修斯指标说明.xlsx”查看所有指标名称、标签以及对应描述。</p>
<h2>【2.3】接入步骤</h2>
<ul>
<li><strong>编译代码</strong>:记得关注<code>common.hrl</code>头⽂件,涉及到 <code>?ERR、?DEBUG、?INFO</code> </li>
<li><strong>设置开服时启动</strong>:以诗悦旧框架举例,在<code>services.erl</code>模块,将<code>prom_mgr</code>设置启动,并<strong>优先于</strong>其他进程启动。优先启动的原因是我们可能需要对某些进程进⾏监控,此时需要<code>prom_mgr</code>已经启动完毕。</li>
</ul>
<pre><code>%% 例⼦1:arena_mgr.erl 某个需要被监控的进程,该进程有注册名
init([]) -&gt;
?INFO(&quot;[~w] 正在启动...&quot;, [?MODULE]),
process_flag(trap_exit, true),
prom_mgr:register_vm_process(self()),
?INFO(&quot;[~w] 启动完成&quot;, [?MODULE]),
{ok, #state{}}.
%% 例⼦2:role.erl 某个需要被监控的进程,该进程有注册名。但因为有⼤量类似进程,增
加“组”概念⽅便批量注销。
init([]) -&gt;
?INFO(&quot;正在启动...&quot;),
process_flag(trap_exit, true),
?INFO(&quot;启动完成&quot;),
prom_mgr:register_vm_process(self(), #{group =&gt; role}),
{ok, #state{}}.
%% 例⼦3:battle.erl 某个需要被监控的进程,该进程没有注册名,在grafana界⾯看起来
信息不明显,所以增加⼀个desc。
init([]) -&gt;
?INFO(&quot;正在启动...&quot;),
process_flag(trap_exit, true),
?INFO(&quot;启动完成&quot;),
Desc = bitstring:concat([Battle#battle.id]),
prom_mgr:register_vm_process(self(), #{group =&gt; battle, desc =&gt;
Desc}),
{ok, #state{}}.</code></pre>
<h2>【2.4】修改头文件</h2>
<pre><code>%% TODO 需要配置的信息列表
%% 最终上报URL = ?gateway_url ++ &quot;/job/&quot; ++ ?job_name ++ &quot;/instance/&quot; ++
?prom_p ++ ?prom_z
%% gateway的地址
-ifdef(debug).
-define(gateway_url, &quot;http://soar.prom/gateway/metrics&quot;).
-else.
-define(gateway_url, &quot;http://soar.prom/gateway/metrics&quot;).
-endif.
%% 项⽬标识 对应url
-define(job_name, &quot;soar&quot;).
%% 获取到区服名称的⽅法
-define(prom_p, env:get(platform)).
%% 获取到区号的⽅法
-define(prom_z, env:get(zone_id)).
%% 开启区服列表
-define(open_list, [{&lt;&lt;&quot;dev&quot;&gt;&gt;, 1}]).
%% 推送定时时间(根据项⽬实际情况修改)
-define(push_default_interval, 30 * 1000).
%% 已注册的采集器 如果加了⾃定义指标模块 需要注册到这⾥
-define(registry_collector, [
prom_vm
]).</code></pre>
<h1>三、方案二:Prometheus监控系统SDK</h1>
<h2>【3.1】整体架构图</h2>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=ff6b4daf80e74ff334aff6042b2d18cf&amp;file=file.png" alt="" /></p>
<p><strong>本SDK集成Prometheus Exporter和Consul的Erlang SDK </strong></p>
<ul>
<li><strong>Prometheus Exporter</strong>:Prometheus定义的概念,提供一个HTTP服务端口,返回OpenMetrics标准的格 式化指标。 </li>
<li><strong>Consul</strong>:consul是一个“服务发现”服务,Prometheus原生支持的组件。</li>
</ul>
<h2>【3.2】接入</h2>
<ul>
<li><strong>文件清单</strong></li>
</ul>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=2a1eea5ff57350b8e43b1c75f314b7a0&amp;file=file.png" alt="" /></p>
<ul>
<li><code>include/</code> 头文件 </li>
<li><code>src/</code> 源码相关
<ul>
<li><code>prometheus/ prometheus.erl</code>库,实现Prometheus的数据模型,附带几个Erlang VM的数 据采集器,<code>sy_game_expoter</code>的可视化表盘大部分数据都基于这些采集器。 </li>
<li><code>prometheus_httpd/ prometheus-httpd</code>库,提供了http格式化相关库,并可以使用httpd 启动Expoter。 </li>
<li><code>metrics/ Prometheus Exporter SDK</code>。本SDK使用了Erlang的httpd和cowboy两种方式实现 HTTP服务,默认以httpd方式启动,可通过修改sy_game_exporter模块的宏USE_COWBOY使 用cowboy。 </li>
<li><code>service_discovery/</code> 服务发现SDK。</li>
</ul></li>
</ul>
<h2>【3.3】配置</h2>
<ul>
<li>在<code>sy_game_exporter.hrl</code>头文件中需要修改<code>EXPORTER_GAME_NAME_CH</code>,<code>EXPORTER_GAME_NAME_EN</code>两个 宏,用于在服务发现中区分不同项目,建议修改为使用Erlang应用配置的方式配置。 </li>
<li>在Erlang应用配置中,需要添加以下的prometheus配置使<code>sy_game_collector</code>采集器生效,添加<code>consul</code>配置指向服务地址</li>
</ul>
<pre><code>[
%% 原来的配置
{server_game, [...]},
%% 服务发现地址
{consul_cfg, [
{consul_host,&quot;124.222.148.13&quot;},
{consul_port, &quot;8500&quot;}
]},
%% 需要添加的配置
{prometheus, [
%% 采集器配置
{collectors, [
%% 项目定制
sy_game_collector,
%% 自带,可关闭
prometheus_boolean,
prometheus_counter,
prometheus_gauge,
prometheus_histogram,
prometheus_mnesia_collector,
prometheus_quantile_summary,
prometheus_summary,
%% 以下自带的采集器,提供了大部分通用可视化表盘的数据,所以开启
prometheus_vm_dist_collector,
prometheus_vm_memory_collector,
prometheus_vm_msacc_collector,
prometheus_vm_statistics_collector,
prometheus_vm_system_info_collector
]}
]}
].
</code></pre>
<h2>【3.4】风险</h2>
<ul>
<li>
<p>目前在以上述配置方式全开采集器的情况下长时间运行测试,服务端平稳运行,单次采集时间约30毫秒。 </p>
</li>
<li>
<p>模拟遭受攻击的情况下,以高TPS请求端口,请求会不断堆积,导致最终节点OOM瘫痪。据此可酌情加入缓存、读写分离等策略规避风险。<strong>本SDK在HTTP请求处使用ets加了个10秒缓存,但是ets:lookup和 ets:insert是两个操作不是原子操作,极端情况下还是会有风险。如需规避极端情况建议用单进程写, http请求仅读取ets的方式。</strong></p>
</li>
<li>在自定义采集器的时候,注意不要加入性能消耗较大的逻辑,否则当单次请求耗时过高,在下次请求到来还未能处理完的的时候,就会陷入同上述一样OOM瘫痪的情况。</li>
</ul>
<h2>【3.5】自定义采集</h2>
<ul>
<li>
<p>参照<code>sy_game_collector.erl</code>和<code>sy_game_metrics.erl</code>,自行开发采集器,并添加到Erlang应用配置中。 </p>
</li>
<li>参照附带的prometheus文档,设计grafana表盘,导出模板给运维组。</li>
</ul>
<h1>四、Prometheus入门文档参考</h1>