乔治于2021年10月16日 服务拓扑 服务发现

使用服务器部署服务的时候,各个服务之间的依赖关系通常是需要额外的工作来维护的。比如有一个MySQL数据库,在典型的运维场景,你想知道哪些应用依赖他就比较费劲,尤其是在一个变换频繁的团队中是需要一个统筹来管理的。 开源项目reploop-topology的目的就是快速发现服务拓扑,其基本假设是一台机器提供服务必须要监听服务端口,并且建立网络连接。这是典型的分布式场景下通过网络连接起来的多机器之间的交互方式。

拓扑

主要利用lsofps命令获取主机上的监听的端口与服务进程。 需要在目标机器上执行如下命令:

sudo lsof -i 4 -nPR;
sudo ps -ef;

lsof 命令获取机器上的所有网络连接,其中也包括了本地监听的端口信息,同时利用ps取得机器上的所有的服务进程。接着通过lsofps的输出结果中的相同的pid可以将网络连接归属到同一个服务进程,并且发现了进程之间的依赖关系。 接着将服务进程通过启动命令归属到同一个应用服务,这样就通过网络连接建立起此连接两端对应的服务之间的连接关系。

一个网络连接,我们经常用5元组来唯一表示: (Source IP, Source Port, Destination IP, Destination Port, Protocol)。这就是源地址IP:Port,目的地址IP:Port ,以及相应的网络协议。下面就开始从基础的名词开始构建服务拓扑。

名词

IP

IP地址,每个网卡(NIC)有一个IP地址,并且在其子网内是唯一的。

Port

网络端口,对于TCP协议,每个机器上是唯一的,同一时间不能被多个应用复用。有些端口是临时端口,可也就是只会出现一次的那种,处理的时候要注意。根据协议不同,有可能是TCP或者UDP协议。 TCP和UDP可以公用同一个端口,比如DNS服务可以同时绑定tcp/53和udp/53端口。 对于UDP的来说,一个端口可以同时被多个不同的应用绑定。

Process

服务进程, 通过服务主入口区分不同的进程。也就是启动命令与main函数的命名空间。

Server

机器,物理上的一台机器或者虚拟机。每台机器可以有多个网卡(NIC),也就是多个IP。

Server Port

服务器端口,一个服务的基本服务形式,一个服务上监听一个服务端口。 这里用(服务器:端口)取代通常理解的(IP:PORT)的形式,来处理一台机器上多网卡的情况。

Service

应用服务,应用层面的服务,不考虑部署结构的应用服务。 这里需要注意的是一个服务可以仅仅作为请求的发起方(client模式),从而不监听任何服务器端口。

ER图

ER图

通过lsof输出的网络连接IP:PORT→IP:PORT最终建立起Service之前的拓扑关系。

服务拓扑

服务拓扑

这里也可以看出,通常一个服务既可以作为客户端依赖其他服务,也可以作为服务器提供服务。

IP地址处理

在一个服务器上监听一个端口,通常有几种写法:

  • *:Port, 监听所有网卡端口,也就是机器上的所有IP都可以访问这个端口。

  • 0.0.0.0:Port, 监听IPv4的端口,

以及本地回环地址127.0.0.1。 这些地址都将会处理为具体的IP地址。 具体是首先会通过lsof的输出结果中汇总出有连接建立的所有本地IP地址,然后用这些IP地址来替换上面出现的特殊形式的IP地址。

Process关系

Linux服务器上的每个Process都有两个id,分别是PID与PPID。同一时刻服务器上的所有PID是不重复的,但是已经消亡的进程PID后面是可以重复被利用的。

Linux下进程之间是一个树的关系,一个进程通过PPID指向其父进程。这点在处理lsof的输出时很重要,因为一个进程本身可以监听端口,也可以让子进程去监听端口提供服务。比如一些守护进程做的事就是其他真正的服务子进程去服务,自己则是一直监控着子进程的健康状态。 但是所有的子进程都应该看作一个服务进程来处理。

缺点

短连接场景

lsof运行的时机很重要,可能采集不到或者不全。

定时任务

同样也是lsof的运行时机很重要,可能采集不到或者不全。

外部服务

第三方服务识别需要提前标注。此部分针对的是机器不能登陆的情况下,获取不到具体信息的情况,都归类为外部第三方服务。 如果有用到Aliyun的话,可以结合Aliyun的Open API,识别出阿里云上的SLB,数据库等资源,使得整个拓扑更清晰。

多进程与进程管理

通过Linux系统进程管理与监控工具启动的服务,真正服务的是子进程,这个影响服务的识别。

应用场景

以下是一些典型的应用场景:

发现空闲机器

机器上没有服务进程的话,可以认为机器是空闲的。或者可以辅以其他信息识别空闲机器。

理解服务拓扑

理解服务之间的调用依赖关系。在抄抄代码的开发模式下,可能会无意引入不必要的服务。

识别意外服务

一般应用服务非常好理解,但是这些服务所依赖的辅助服务,经常被忽略。比如读写文件系统,日志监控服务等。

结论

在微服务体系下,调用链是必备的。通过他也是可以画出服务拓扑关系的。也就不需要这么麻烦了。

参考