🦋
Butterfly 用户手册
  • Introduction
  • 一 前言
  • 二 开始
    • 安装部署
    • 五分钟体验指南
    • 单机使用手册
    • 应用规范
      • handler specs
      • middleware specs
      • xingqiao_plugin specs
      • yiqiu_program specs
  • 三 客户端功能
    • MySQL 原生协议
    • MySQL ORM
    • Redis 原生协议
      • redis_config
      • redis_tls
    • Redis ORM
    • Redis mcpack
    • Localcache
    • Kazoo
  • 四 应用(通用服务)
    • API JSON 规范
    • 异步任务 BaiChuan(百川)
    • 任务调度 RuQi(如期)
    • 任务编排 XingQiao(星桥)
    • 配置管理 WuXing(五行)
    • 运筹决策 BaiCe(百策)
  • 五 部署运维
    • 单机容器化部署
    • 监控
    • 异常排查
      • CPU Load spike every 7 hours
    • 升级
    • 安全
    • 其他
  • 六 前端
    • butterfly_template
    • butterfly_fe
    • butterfly-admin(json2web)
      • amis
      • sso
      • pangu
    • NoahV
    • PyWebIO
  • 七 潘多拉魔盒
    • 装饰器
      • localcache_decorator
      • retry_decorator
      • custom_decorator
      • command2http_decorator
    • 算法
      • 算法-分位数
      • 算法-变异系数
    • 实用工具
      • host_util
      • shell_util
      • http_util
      • time_util
      • random_util
      • concurrent
      • jsonschema
      • blinker
      • toml
      • command_util
      • config_util
      • picobox
      • 对称加密
        • des
        • aes
      • ascii_art
        • ttable
        • chart
      • business_rules
      • python-mysql-replication
      • dict_util
    • 中间件
      • middleware_status
      • middleware_whitelist
    • test_handler.py
  • 八 最佳实践
    • 分布式架构
    • Code practice
    • Log practice
    • Daemon process
  • 附录
Powered by GitBook
On this page
  • 1 handler
  • 2 管理脚本
  • 2.1 PROC_SIG
  1. 八 最佳实践

Daemon process

场景:

监听 MySQL binlog 变更,将关注的事件发送到对应服务,代码逻辑中依赖 xlib、已有 handler

所以此常驻的服务也使用 handler 实现

1 handler

若非命令行请求此 handler,则直接返回 ERR

@funcattr.api
def event_send(req, log_file=None, log_pos=None):
    """
    event send
    """
    if req.wsgienv.get("REQUEST_METHOD", "UNKNOW") != "COMMAND":
        req.error_str = "req method is not command"
        return retstat.ERR

    try:
        _event_send(req, log_file=log_file, log_pos=log_pos)
    except BaseException:
        logger.error("action:event_send_except, version:{}, err_msg:{}".format(__version, traceback.format_exc()))

    return retstat.OK

2 管理脚本

#!/bin/bash

CUR_DIR=$(cd `dirname $0`; pwd)
cd ${CUR_DIR}

EXEC="python2.7"
STDOUT="${CUR_DIR}/logs/__app_stdout"
APP_PATH=$1
APP_PATH="${APP_PATH%/}"                            # 移除结尾的斜杠
if awk -F'/' 'NF==3' <<< "$APP_PATH" && [[ "$APP_PATH" == /* ]]; then
    :   # 这是一个空操作,相当于什么都不做
else
    # usage
    echo -e "\nUsage: $0 APP {start|stop|restart|status}"
    echo -e ${WITE}" APP start         "${NC}"Start app processes."
    echo -e ${WITE}" APP stop          "${NC}"Kill all app processes."
    echo -e ${WITE}" APP restart       "${NC}"Kill all app processes and start again."
    echo -e ${WITE}" APP status        "${NC}"Show app processes status."
    echo "app examples: /app_event/event_send"
    exit 1
fi
STATUS_DIR_NAME_TMP="${APP_PATH#/}"                 # 移除开头的斜杠
STATUS_DIR_NAME="${STATUS_DIR_NAME_TMP//\//-}"      # 将所有剩余的斜杠替换为短横线

DISP_NAME=$APP_PATH
PROC_SIG="95421699"

# Consts
RED='\033[1;91m'
GREN='\033[1;92m'
WITE='\033[1;97m'
NC='\033[0m'

# Global vailables
PROC_COUNT="0"
function count_proc()
{
    PROC_COUNT=$(ps -ef | grep $APP_PATH | grep $PROC_SIG |grep -vc grep)
}
function list_proc()
{
    ps -ef | grep -v grep | grep $PROC_SIG |grep --color $APP_PATH
}
function list_proc_pids()
{
    ps -ef | grep $APP_PATH | grep $PROC_SIG | grep -v grep | awk '{print $2}'
}

function start_procs()
{
    mkdir -p ./status/${STATUS_DIR_NAME}
    printf "Starting $DISP_NAME processes"
    count_proc
    if [ $PROC_COUNT \> 0 ]; then
        echo
        list_proc
        echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed, processes already runing."
        exit 0
    fi
    date >> $STDOUT
    supervise -p ${CUR_DIR}/status/${STATUS_DIR_NAME} -f "${EXEC} ${CUR_DIR}/test_handler.py ${APP_PATH} --PROC_SIG=${PROC_SIG}"

    sleep 1
    list_proc
    count_proc
    if [ $PROC_COUNT == 0 ]; then
        echo -e ${RED}"\n[ERROR]" ${NC}"Start $DISP_NAME failed."
        exit -1
    fi

    echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME start succesfully."
}

function stop_procs()
{
    printf "Stoping $DISP_NAME"
    count_proc
    if [ ${PROC_COUNT} -eq 0 ]; then
        echo -e ${RED}"\n[ERROR]" ${NC}"$DISP_NAME process not found."
        return
    fi

    # stop process
    kill -15 $(list_proc_pids)
    count_proc
    check_count=0
    while [ ${PROC_COUNT} -ne 0 ]; do
        printf "."
        sleep 0.2
        count_proc

        let check_count=$check_count+1
        if [[ ${check_count} > 10 ]]
        then
            kill -9 $(list_proc_pids)
        fi
    done
    echo -e ${GREN}"\n[OK]" ${NC}"$DISP_NAME stop succesfully."
}

function status_procs()
{
    count_proc
    echo -e ${RED}${PROC_COUNT}${NC} "$DISP_NAME processes runing."
}


MODE=${2}
case ${MODE} in
    "start")
        start_procs
        ;;

    "stop")
        stop_procs
        ;;

    "restart")
        stop_procs
        start_procs
        ;;

    "status")
        status_procs
        ;;
    *)
        # usage
        echo -e "\nUsage: $0 APP {start|stop|restart|status}"
        echo -e ${WITE}" APP start         "${NC}"Start app processes."
        echo -e ${WITE}" APP stop          "${NC}"Kill all app processes."
        echo -e ${WITE}" APP restart       "${NC}"Kill all app processes and start again."
        echo -e ${WITE}" APP status        "${NC}"Show app processes status."
        exit 1
        ;;
esac

2.1 PROC_SIG

--PROC_SIG=95421699 仅作为进程标识使用,防止意外 kill 包含 "$APP_PATH" 字符串的其他进程
test_handler.py 会自动过滤非 handler 的参数
PreviousLog practiceNext附录

Last updated 11 months ago