业务爸爸需求: 写一个脚本用于向 Consul 注册或注销服务。


(资料图片)

Consul API 实现服务的注册和注销功能

拿到这个需求,我第一时间想到是用 curl 调用 Consul API 实现服务的注册和注销功能。 如下:

#!/bin/bashCONSUL_TOKEN="<your_token_here>"CONSUL_URL="http://localhost:8500"function register_service {  curl \    --request PUT \    --header "Content-Type: application/json" \    --header "X-Consul-Token: ${CONSUL_TOKEN}" \    --data "@- ${CONSUL_URL}/v1/agent/service/register" <<EOF{  "ID": "${1}",  "Name": "${2}",  "Address": "${3}",  "Port": ${4}}EOF}function deregister_service {  curl \    --request PUT \    --header "X-Consul-Token: ${CONSUL_TOKEN}" \    "${CONSUL_URL}/v1/agent/service/deregister/${1}"}# example usageregister_service "my-service" "My Service" "localhost" 8080deregister_service "my-service"

在这个实现中,我们将认证token存储在CONSUL_TOKEN变量中,并在curl请求中使用--header "X-Consul-Token: ${CONSUL_TOKEN}"来添加它。

这个是可以实现业务爸爸的需求, 但是,这种实现有以下几个问题:

1. 不能批量添加相同的类型的指标。

2. 唯一ID需要手动维护。

3. 没有配置文件留底,虽然三节点的consul集群很小概率同时出问题, 但是有留底还是一个很好习惯。

基于这个几个点, 写入下面实现脚本。

register 和 deregister实现

#!/bin/bash# author 小毛驴# SHELL_DIR=$(cd $(dirname $0);pwd)BACKUP_DIR=${SHELL_DIR}"/consulbackup"SOURCEFILE=${SHELL_DIR}"/origin.json"LOGFILE=${SHELL_DIR}"/add.log"BASESVCRIR=/data/consul/config/TOKENFILE=/data/consul/consul_token.yaml OPTION=${OPTION:="1"}ENV=${ENV:="prod"}PROJECT=${PROJECT:="fb"}MODULE=${MODULE:="api"}SERVICENAME=${SERVICENAME:="node-exporter"}NAME=${NAME:="core"}TAG=${TAG:="node-exporter"}IPADDRS=""IPADDR=""PORT=${PORT:="9520"}LEGAL_IP="^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$"if [ ! -e "${BACKUP_DIR}" ];then    mkdir -p ${BACKUP_DIR}fifunction usage(){        echo -e "\nUsage: $0 <option> <value>"        echo -e "\n option:"        echo -e "\n -o,--option    option name, default 1:add , 2:delete"        echo -e "\n -e,--env       env name, default prod"        echo -e "\n -p,--project   project name, default fb"        echo -e "\n -m,--module    module name, default api"        echo -e "\n -n,--name      api name, default core"        echo -e "\n -s,--svcname   serviceName name, default node-exporter"        echo -e "\n -t,--tag       tag name, default node-exporter"        echo -e "\n -a,--address   ip address, eg 1.1.1.1|2.2.2.2 default '' [Require]"        echo -e "\n -i,--interface interface num default 9520"        echo -e "\n -h,--help      help"}function checkIp(){    #正则表达式检验 ip 地址    [[  $1 =~ $LEGAL_IP ]]    if [ $? -gt 0 ]; then        echo "$1 is an error ip fromat"        exit 10    fi}function svcDeregister() {    if [ ! -e "$1" ];then        echo "$1 not exit, please check!"    else        /bin/consul services deregister  -token-file=${TOKENFILE}  $1    fi}function svcRegister() {    if [ ! -e "$1" ];then        echo "$1 not exit, please check!"    else        /bin/consul services register  -token-file=${TOKENFILE} $1    fi}function genJson() {cat > "${SERVICENAME}-${ENV}-${PROJECT}-${MODULE}-${NAME}-${IPADDR}.json" <<EOF{  "service": {    "id": "${SERVICENAME}-${ENV}-${PROJECT}-${MODULE}-${NAME}-${IPADDR}",    "name": "${SERVICENAME}",    "tags": [       "${TAG}"    ],    "address": "${IPADDR}",    "port": ${PORT},    "meta": {      "name": "${NAME}-${IPADDR}",      "module": "${MODULE}",      "project": "${PROJECT}",      "env": "${ENV}"    },    "check": {      "http": "http://${IPADDR}:${PORT}/metrics",      "interval": "10s"    },    "weights": {      "passing": 10,      "warning": 1    }  }}EOF}function removeJson() {    mv "${SERVICENAME}-${ENV}-${PROJECT}-${MODULE}-${NAME}-${IPADDR}.json"  ${BACKUP_DIR}}function main() {    if (($# == 0));then        usage        exit    fi    cd ${SHELL_DIR}    while [ -n "$1" ];do        case $1 in         -o|--option )            OPTION=$2            shift            ;;        -e|--env )            ENV=$2            shift            ;;        -p|--project )            PROJECT=$2            shift            ;;        -m|--module  )            MODULE=$2            shift            ;;        -n|--name )            NAME=$2            shift            ;;        -s|--svcname )            SERVICENAME=$2            shift            ;;        -t|--tag )            TAG=$2            shift            ;;        -a|--address )            IPADDRS=$2            shift            ;;        -i|--interface )            PORT=$2            shift            ;;        -h|--help )            usage            exit            ;;        *)            echo -e "\n$1 unknow an option"            usage            exit        esac        shift     done    if [ "${IPADDRS}"x == ""x ];then        echo -e "\n-a|--address option is Require"        usage        exit    fi    SVCRIR="${BASESVCRIR}/${SERVICENAME}"    if [ ! -e "${SVCRIR}" ];then        mkdir -p ${SVCRIR}    fi    cd ${SVCRIR}    hosts=($(echo ${IPADDRS} | sed 's/|/ /g'))    for(( i=0;i<${#hosts[@]};i++))     do        echo ${hosts[$i]}        checkIp ${hosts[$i]}        IPADDR="${hosts[$i]}"        if [[ "${OPTION}"x == "1"x  ]]; then            genJson            #statements            svcRegister "${SERVICENAME}-${ENV}-${PROJECT}-${MODULE}-${NAME}-${IPADDR}.json"         fi        if [[ "${OPTION}"x == "2"x  ]]; then            #statements            svcDeregister "${SERVICENAME}-${ENV}-${PROJECT}-${MODULE}-${NAME}-${IPADDR}.json"             removeJson        fi    done }main $@

这个脚本首先定义了BACKUP_DIR,BASESVCRIR 和TOKENFILE 等路径。

用法

./register-service.sh [OPTIONS]参数-h, --help: 显示帮助信息并退出。-o, -option: 1 register ; 2 deregister-e,--env       环境标识, default prod-p,--project  项目名字, default fb-m,--module   业务模块名, default api-n,--name      模块下面的应用名, default core-s,--svcname   service 名字, default node-exporter-t,--tag       tag 名字, default node-exporter-a,--address   需要注册到该服务的地址,多个以“|”分开,, eg 1.1.1.1|2.2.2.2 default '' [Require],必须提供-i,--interface  需要注册的端口 9520

./register-service.sh -o 1 -e prod -p fb -m ops -n consul-ops -s consul_exporter-t consul_exporter -a "10.2.0.6|10.2.0.10|10.2.0.41" -i 9107

推荐内容