• 深入学习keepalived之一 keepalived的启动


    1.keepalived的启动过程:

        启动健康检查子进程和vrrp子进程。其中_WITH_LVS_,_WITH_VRRP_在configure和configure.in文件中定义。

    源码如下:

    /* Daemon init sequence */
    static void
    start_keepalived(void)
    {
    #ifdef _WITH_LVS_
        /* start healthchecker child */
        if (daemon_mode & 2 || !daemon_mode)
            start_check_child();
    #endif
    #ifdef _WITH_VRRP_
        /* start vrrp child */
        if (daemon_mode & 1 || !daemon_mode)
            start_vrrp_child();
    #endif
    }

    2. 启动健康检查子进程。

    /* Register CHECK thread */
    int
    start_check_child(void)
    {
    #ifndef _DEBUG_
        pid_t pid;
        int ret;
    
        /* Initialize child process */
        pid = fork();
    
        if (pid < 0) {
            log_message(LOG_INFO, "Healthcheck child process: fork error(%s)"
                       , strerror(errno));
            return -1;
        } else if (pid) {
            checkers_child = pid;
            log_message(LOG_INFO, "Starting Healthcheck child process, pid=%d"
                       , pid);
    
            /* Start respawning thread */
            thread_add_child(master, check_respawn_thread, NULL,
                     pid, RESPAWN_TIMER);
            return 0;
        }
    
        /* Opening local CHECK syslog channel */
        openlog(PROG_CHECK, LOG_PID | ((debug & 1) ? LOG_CONS : 0),
            (log_facility==LOG_DAEMON) ? LOG_LOCAL2 : log_facility);
    
        /* Child process part, write pidfile */
        if (!pidfile_write(checkers_pidfile, getpid())) {
            log_message(LOG_INFO, "Healthcheck child process: cannot write pidfile");
            exit(0);
        }
    
        /* Create the new master thread */
        signal_handler_destroy();
        thread_destroy_master(master);
        master = thread_make_master();
    
        /* change to / dir */
        ret = chdir("/");
        if (ret < 0) {
            log_message(LOG_INFO, "Healthcheck child process: error chdir");
        }
    
        /* Set mask */
        umask(0);
    #endif
    
        /* If last process died during a reload, we can get there and we
         * don't want to loop again, because we're not reloading anymore.
         */
        UNSET_RELOAD;
    
        /* Signal handling initialization */
        check_signal_init();
    
        /* Start Healthcheck daemon */
        start_check();
    
        /* Launch the scheduling I/O multiplexer */
        launch_scheduler();
    
        /* Finish healthchecker daemon process */
        stop_check();
        exit(0);
    }

    debug模式暂且不考虑。

    2.1 健康检查信号初始化

    /* CHECK Child signal handling */
    void
    check_signal_init(void)
    {
        signal_handler_init();
        signal_set(SIGHUP, sighup_check, NULL);
        signal_set(SIGINT, sigend_check, NULL);
        signal_set(SIGTERM, sigend_check, NULL);
        signal_ignore(SIGPIPE);
    }
    
    
    /* Handlers intialization */
    void
    signal_handler_init(void)
    {
        int n = pipe(signal_pipe);
        assert(!n);
    
        fcntl(signal_pipe[0], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[0], F_GETFL));
        fcntl(signal_pipe[1], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[1], F_GETFL));
    
        signal_SIGHUP_handler = NULL;
        signal_SIGINT_handler = NULL;
        signal_SIGTERM_handler = NULL;
        signal_SIGCHLD_handler = NULL;
    }

    2.2 启动健康检查后台程序

    /* Daemon init sequence */
    static void
    start_check(void)
    {
        /* Initialize sub-system */
        ipvs_start();
        init_checkers_queue();
    #ifdef _WITH_VRRP_
        init_interface_queue();
        kernel_netlink_init();
    #endif
    #ifdef _WITH_SNMP_
        if (!reload && snmp)
            check_snmp_agent_init();
    #endif
    
        /* Parse configuration file */
        global_data = alloc_global_data();
        check_data = alloc_check_data();
        init_data(conf_file, check_init_keywords);
        if (!check_data) {
            stop_check();
            return;
        }
    
        /* Post initializations */
        log_message(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated);
    
        /* SSL load static data & initialize common ctx context */
        if (!init_ssl_ctx()) {
            stop_check();
            return;
        }
    
        /* Processing differential configuration parsing */
        if (reload) {
            clear_diff_services();
            copy_srv_states();
        }
    
        /* Initialize IPVS topology */
        if (!init_services()) {
            stop_check();
            return;
        }
    
        /* Dump configuration */
        if (debug & 4) {
            dump_global_data(global_data);
            dump_check_data(check_data);
        }
    
    #ifdef _WITH_VRRP_
        /* Initialize linkbeat */
        init_interface_linkbeat();
    #endif
    
        /* Register checkers thread */
        register_checkers_thread();
    }

    2.3 启动I/O复用分发调度器

    /* Our infinite scheduling loop */
    void
    launch_scheduler(void)
    {
        thread_t thread;
    
        signal_set(SIGCHLD, thread_child_handler, master);
    
        /*
         * Processing the master thread queues,
         * return and execute one ready thread.
         */
        while (thread_fetch(master, &thread)) {
            /* Run until error, used for debuging only */
    #ifdef _DEBUG_
            if ((debug & 520) == 520) {
                debug &= ~520;
                thread_add_terminate_event(master);
            }
    #endif
            thread_call(&thread);
        }
    }
  • 相关阅读:
    redis 储存对象
    redis key 查看器
    c# 控制台程序编写RabbitMQ 生产者
    C# 使用Topshelf 构建 基于 window 服务的 RabbitMQ消费端
    asp.net webapi 使用定时任务Hangfire
    asp.net webpi 中使用 ClientHelper 发起HTTP请求
    SQL Server 导入和导出向导 未在本地计算机上注册Mircrosoft.ACE.OLEDB.12.0 提供程序
    c# 使用Linq 表达式 对查询结果分组,保留价格最低的一条
    Asp.Net s请求报传输流收到意外的 EOF 或 0 个字节
    asp.net webapi 中使用rdlc 报表
  • 原文地址:https://www.cnblogs.com/davidwang456/p/3543098.html
Copyright © 2020-2023  润新知