给 skynet 增加网络统计
skynet 在这个阶段的工作,主要是增强运行时内部信息的透明性。多提供运行时的统计数据可以为运维工作提供方便,也能为性能调优给出指导方向。
最近,我给 debug console 增加了 netstat 指令,以及提供了配套的 socket.netstat api 来获取这些数据。
这个指令可以获取 skynet 创建的所有 socket 的列表。每个 socket 归属于哪个 service ,每个 socket 上读写的字节数,最后一次读和写发生的时间,未写入系统挂在代写链表上的字节数。当然还有每个 fd 对应的 ip 地址和端口(如果是 socket )。如果是 listen fd ,会纪录 accept 成功的次数,
这些数据通过系统的 netstat 指令也可以查到,但是由 skynet 提供,可以查到更多细节:最关键的内部信息是一个 socket 被绑定在 skynet 的哪个内部服务上,这是系统的 netstat 无法提供的信息。
在设计获取统计信息 api 的时候,我的第一个想法是向 socket 线程发送一个控制信号,然后由 socket 线程做统计,然后通过 socket 数据结构返回。这样可以回避多线程问题;这类查询似乎也不太在乎是同步还是异步的。
但经过几个小时的思考和推敲,我否定了这个做法。
这样做的确可以简化多线程的处理,但是扩展 socket 消息结构却又可能对过去的代码照成潜在的兼容性风险。虽然这个风险不大,最坏情况只是造成查询结果的内存泄漏。
另外,由于查询结果是个复杂数据结构,必须由接收方来释放内存,把结果投递到制定服务同样也有内存泄漏的风险。
更重要的一点是,异步查询的接口使用起来会麻烦一些。
所以,最后我还是设计了一个同步查询 api 。因为这些统计数据只是用来参考,我们不用特别为一致性考虑。我们得到的数据并不是某个时间点的网络状态的快照。这些统计数据是从 socket 线程之外获取的,在获取过程中,可能在变化,但我认为没有什么坏影响。得益于 skynet 使用的是固定大小的 socket 数据结构数组(默认最大支持同时 64K 个 socket ,可以通过编译配置宏增加),我们不必特别考虑多线程下 socket 数据结构的生命期问题,增加这个统计查询还是挺容易,用一个 double check 就可以保证查询到的单个 socket 的统计数据是有效的,不需要额外加锁。
新特性的使用方法是,登录 skynet 的 debug console 输入 netstat ,或者可以通过 http 协议向 debug console 索取:wget –q –O - http://127.0.0.1:8000/netstat 。
也可以调用 socket.netstat() 获得详细的信息(返回在一个 lua table 中)。
Comments
Posted by: 时空之源sb | (5) September 26, 2018 05:51 PM
Posted by: 时空之源sb | (4) September 26, 2018 11:01 AM
Posted by: heibor | (3) September 19, 2018 03:46 PM
Posted by: 时空之源sb | (2) September 18, 2018 09:52 AM
Posted by: 时空之源 | (1) September 14, 2018 04:59 PM