一架梯子,一头程序猿,仰望星空!

Consul 服务健康检查


分布式环境下,微服务实例的重启、微服务异常等等,都会导致服务不可用,例如:我们向consul注册了一个web服务,web服务启动了10个实例,现在有3个实例不可用,consul怎么知道那些服务实例不可用?

consul健康检查机制,就是解决上述问题的解决方案,健康检查机制运行在consul client中,会定期的根据服务的健康检查配置,去检测服务是否正常,如果服务异常,就将服务的实例标记为不用,如果恢复了,就标记为可用。

健康检查基本配置格式,是在服务定义配置中,增加checks字段,配置健康检查。

{
 "service": {
     "name": "web",
     "tags": ["rails"],
     "port": 80,
     "checks" : [
          {
            ...具体的健康检查配置...
           }
      ]
  }
}

consul健康检查有多种方式,具体的配置,参考下面。

提示:下面的例子,以一个web服务的配置为例子,介绍健康检查的配置,web服务端口号为80。

1.基于HTTP请求

定时以GET请求方式,请求指定url,http请求返回状态码200表示正常,其他状态代表异常。

例子:

{
	"service": {
		"name": "web",
		"tags": ["rails"],
		"port": 80,
		"checks": [{
			"id": "api", // 健康检查项的id,唯一
			"name": "HTTP API on port 5000", // 检查项的名字
			"http": "https://localhost:5000/health", // 定期访问的Url,通过这个url请求结果确定服务是否正常
			"tls_skip_verify": false, // 关闭tls验证
			"method": "POST", // 设置http请求方式,默认是GET
			"header": { // 可以自定义请求头,可以不配置
				"x-foo": ["bar", "baz"]
			},
			"interval": "10s", // 定期检查的时间间隔,这里是10秒
			"timeout": "1s" // 请求超时时间,1秒
		}]
	}
}

2.基于tcp请求

基于tcp请求方式,就是定时,向指定的地址,建立tcp连接,连接成功就代表服务正常,否则代表异常。

例子:

{
	"service": {
		"name": "web",
		"tags": ["rails"],
		"port": 80,
		"checks": [{
			"id": "ssh", // 检查项目id
			"name": "SSH TCP on port 22", // 检查项名字
			"tcp": "localhost:22", // tcp连接地址,ip+port
			"interval": "10s", // 定义建立连接的时间间隔是10秒
			"timeout": "1s" // 超时时间是1秒
		}]
	}
}

3.基于grpc请求

如果微服务是基于grpc协议,可以使用grpc协议检测服务是否正常。

例子:

{
	"service": {
		"name": "web",
		"tags": ["rails"],
		"port": 80,
		"checks": [{
			"id": "mem-util", // 检查项目id
			"name": "Service health status", // 检查项名字
			"grpc": "127.0.0.1:12345", // grpc地址,ip+port
			"grpc_use_tls": true,
			"interval": "10s" // 10秒检测一次
		}]
	}
}

4.基于命令

consul支持定期执行一个命令或者脚本,来检测服务是否正常;Consul通过检测命令退出状态判断服务是否正常,命令退出状态0代表正常,其他代表异常。

例如:

通过shell脚本检测服务.

#!/bin/bash
# 执行检测任务
# ...忽略...

# 通过exit命令退出脚本,并返回一个整数值,0代表正常
exit 0

提示:通常linux命令,都遵循这个规则,命令正常执行,程序退出状态都是0,报错的话就是大于0的状态。

例子1:

{
	"service": {
		"name": "web",
		"tags": ["rails"],
		"port": 80,
		"checks": [{
			"id": "mem-util", // 检查项id
			"name": "Memory utilization", // 检查项名字
			"args": ["/usr/local/bin/check_mem.py", "-limit", "256MB"], // 这里是我们要执行的命令,第一个参数是命令或者脚本名,后面跟着任意个参数
			"interval": "10s", // 每10秒执行一次命令
			"timeout": "1s" // 命令执行超时时间
		}]
	}
}

例子2:

{
	"service": {
		"name": "web",
		"tags": ["rails"],
		"port": 80,
		"checks": [{
			"args": ["curl", "localhost"], // 执行curl命令,数组第2到第N个元素,代表命令参数
			"interval": "10s" // 每10秒执行一次命令
		}]
	}
}

为了安全考虑,如果健康检查使用执行命令方式,在启动consul的时候支持下面两种参数:

  • -enable-script-checks 允许通过配置文件和http api注册的服务,执行命令检查健康状态
  • -enable-local-script-checks 禁止通过http api注册的服务,执行命令检查健康状态,只允许通过配置文件注册的服务,执行命令。

建议生产环境使用-enable-local-script-checks参数启动consul agent。

例子:

consul agent -dev -enable-local-script-checks -config-dir=/etc/consul.d

本地测试,增加-dev参数,代表开发模式,生产环境,去掉-dev参数。

因为只有consul的client才会执行健康检查任务,可以在client设置这个参数就可以。