node服务的监控预警系统架构

需求背景

目前node端的服务逐渐成熟,在很多公司内部也开始承担业务处理或者视图渲染工做。不一样于我的开发的简单服务器,企业级的node服务要求更为苛刻:node

高稳定性、高可靠性、鲁棒性以及直观的监控和报警linux

想象下一个存在安全隐患且没有监控预警系统的node服务在生产环境下运行的场景,当某个node实例挂掉的状况下,运维人员或者对应开发维护人员没法当即知晓,直到客户或者测试人员报告bugs才开始解决问题。在这段无人处理的时间内,损失的订单数和用户的忠诚度和信任度将是之后没法弥补的,所以对于node程序的业务开发者而言,这就要求代码严谨、异常处理完备;对于node框架的维护者而言,则须要提供完善的监控预警系统算法

功能

当一个服务进程在后端运行时(daemon),做为开发者咱们关注的信息主要有如下几点:数据库

  • 服务进程是否正在运行,isalivejson

  • 服务进程的内存使用率,是否存在未回收(释放)的内存后端

  • 服务进程的cpu使用率,在计算量大的状况下是否须要分片处理、延时处理promise

  • 服务进程的实时响应时间和吞吐量安全

而做为一个运维人员,关注的不只仅是node服务进程的相关信息,还包括物理主机的使用情况:服务器

  • 物理硬盘所剩存储空间网络

  • 内存、cpu使用率

  • 网络接入是否正常

能够看出,不论是针对主机仍是进程进行监控,咱们的关注点大多数是资源使用率和业务量处理能力,所以咱们的监控预警系统也着重实现这些功能。

系统简易架构

目前生产环境下的node服务大多采用多进程或者cluster模式,并且为了响应突发流量每每采用多机部署,所以监控和预警的目标实体就是多物理(虚拟)机下的多个子进程

好比,目前node服务在单机上每每采用1+n的进程模型:所谓1,即1个主进程;n,表示n个工做进程,并且这些工做进程是从主进程上fork出来,同时根据经验,n的值每每等同于主机的cpu核心数,充分利用其并行能力。那么,采用该种进程模型的node服务部署在线上4台物理机上,咱们须要监控的则是4xn个进程,这涉及到了分布式数据同步的问题,须要寻找一种方法实现高效、准确和简易的数据存和读,而且尽量的保证这些数据的可靠性。

在这里,笔者采用了分布式数据一致系统ZooKeeper(下文简写为ZK)实现数据的存和读。之因此没有采用传统的数据库是因为读写表的性能,如为了防止多个进程同时写表形成冲突必须进行锁表等操做,并且读写硬盘的性能相对内存读写较低;之因此没有采用IPC+事件机制实现多进程通讯,主要是因为node提供的IPC通讯机制仅限于父子进程,对于不一样主机的进程没法进行通讯或者实现复杂度较高,所以也并未采用该种方式。

采用ZK来实现多节点下的数据同步,可在保证集群可靠性的基础上达到数据的最终一致性,对于监控系统而言,不须要时刻都精确的数据,所以数据的最终一致性彻底知足系统的需求。ZK服务集群经过paxos算法实现选举,并采用ZK独特的算法实现数据在各个集群节点的同步,最终抽象为一个数据层。这样ZK客户端就能够经过访问ZK集群的任意一个服务节点获取或读写相同的数据,用通俗的语言来形容,就是ZK客户端看到的全部ZK服务节点都有相同的数据。

另外,ZK提供了一种临时节点,即ephemeral。该节点与客户端的会话session相绑定,一旦会话超时或者链接断开,该节点就会消失,并触发对应事件,所以利用该种特性能够设置node服务的isalive(是否存活)功能。不过,目前node社区针对ZK的客户端还不是很完善(主要是文档),笔者采用node-zookeeper-client模块而且针对全部接口promise化,这样在进行多级znode开发时更可读。

建议架构图
上图是笔者设计的监控预警系统的架构图,这里须要着重关注一下几点:

  • ZooKeeper部署与znode节点使用

  • 单机内部node进程的进程模型:1+n+1

  • precaution进程的工做内容以及与master和worker的通讯方式

下面着重详述以上几点。

ZooKeeper部署与编码细节

上节已提到,ZooKeeper抽象为一个数据一致层,它是由多个节点组成的存储集群,所以在具体的线上环境下,ZK集群是由多个线上主机搭建而成,全部的数据都是存储在内存中,每当对应工做进程的数据发生变化时则修改对应znode节点的数据,在具体实现中每一个znode节点存储的是json数据,便于node端直接解析。

在具体的代码中,咱们须要注意的是ZK客户端会话超时和网络断开重连的问题。默认,ZK客户端会帮助咱们完成网络断开后重连过程的简历,并且在从新链接的过程当中会携带上次断开链接的session id,这样在session未超时的前提下仍会绑定以前的数据;可是当session超时的状况下,对应session id的数据将会被清空,这就须要咱们的本身处理这种状况,又称做现场恢复。其实,在监控系统中,因为须要实时查询对应节点数据,须要始终保持session,在设定session expire时间的状况下终究会出现ZK客户端会话超时的状况,所以须要咱们实现现场恢复,须要注意。

进程模型

大多数开发者为了提升node程序的并行处理能力,每每采用一个主进程+多个工做进程的方式处理请求,这在不须要监控预警系统的前提下是能够知足要求的。可是,随着监控预警功能的加入,有不少人估计会把这些功能加入到主进程,这首先不说主进程工做职能的混乱,最主要的是额外增长了风险性(预警系统的职能之一就是打点堆快照,并提醒开发者。所以主进程内执行查询、打点系统资源、发送邮件等工做存在可能的风险)。所以为了主进程的功能单一性和可靠性,建立了一个precaution进程,该进程与主进程同级。

采用1+n+1模型并不会影响请求处理效率,工做进程的职能还是处理请求,所以新的进程模型彻底兼容以前的代码,须要作的就是在主进程和precaution进程执行的代码中添加业务部分代码。

通讯方式

在监控预警系统中,须要实现precaution进程<-->master进程、master进程<-->worker进程、precaution进程<-->worker进程的双向通讯,如打点内存,须要由precaution进程通知对应worker进程,worker进行打点完成后发送消息给precaution进程,precaution进行处理后发送邮件通知。

首先,worker与master的通讯走的是node提供的IPC通道,须要注意的是IPC通道只能传输字符串和可结构化的对象。可结构化的对象能够用一个公式简易表述:

o = JSON.parse(JSON.stringify(o))

如RegExp的实例就不是可结构化对象。

其次,worker和precaution的通讯是经过master做为桥梁实现的,所以其中的关节点就在于precaution与master的通讯。

最后,precaution与master的通讯采用domain socket机制实现,这两个进程是只是两个node实例而已,所以没法采用node提供的IPC机制,而进程间通讯能够采用其余方法如:命名管道、共享内存、信号量和消息队列等,采用这些方法实现当然简单,可是缺点在于两个进程耦合度相对较高,如命名管道须要建立具体的管道文件而且对管道文件大小有限制。使用domain socket,最大的好处就是灵活制定通讯协议,且易于扩展。

node的net模块提供了domain socket的通讯方式,与网络服务器相似,采用domain通讯的服务器侦听的不是端口而是sock文件,采用这种方式实现全双工通讯。

业务量计算和数据打点

这里提到的业务量,指的是监控预警系统所关注的数据业务,如内存和cpu利用率、吞吐量(request per minute)和响应时间。其中,内存和cpu利用率能够经过linux下的相关命令如top来查询,响应时间和吞吐量则经过koa中间件实现粗略统计。不过为了方便开发者把精力集中到业务上去而非兼容底层操做系统,建议使用pidusage模块完成资源利用率的测量,而针对吞吐量笔者并未找到相关的工具进行测量,仅在中间件中粗略计算得出。

在precaution进程中,设置了两个阈值。一个是warning值,当使用内存大小超过了该值则进行日志打点,并开始周期性的node堆内存打点;另外一个是danger值,超过该值则进行内存打点并发送邮件提醒,根据附件中的近三个快照分析内存。

总结

采用上述监控预警架构,能够有效的实现多节点下多进程的监控,在确保进程可靠性的基础上完成侵入性较小的、安全性较高的、可扩展性强的实现。之后不论是临时扩张主机节点仍是更改子进程数量,均可以瞬时在UI界面上直观体现,如节点监控图

相关文章
相关标签/搜索