所有源码分析基于haproxy version 1.6.14

首先分析核心代码haproxy.c

/* Runs the polling loop */
void run_poll_loop()
{
	int next;

	tv_update_date(0,1);
	while (1) {
		/* Process a few tasks */
		process_runnable_tasks();

		/* check if we caught some signals and process them */
		signal_process_queue();

		/* Check if we can expire some tasks */
		next = wake_expired_tasks();

		/* stop when there's nothing left to do */
		if (jobs == 0)
			break;

		/* expire immediately if events are pending */
		if (fd_cache_num || tasks_run_queue || signal_queue_len || applets_active_queue)
			next = now_ms;

		/* The poller will ensure it returns around <next> */
		cur_poller.poll(&cur_poller, next);
		fd_process_cached_events();
		applet_run_active();
	}
}

简要说明

  1. process_runnable_tasks 处理可运行的任务
  2. signal_process_queue 处理信号队列,如果捕获了信号则需要处理
  3. wake_expired_tasks 处理超时任务
  4. cur_poller.poll 更新fd事件到缓存
  5. fd_process_cached_events 处理fd事件

函数分析

整体描述下函数的作用

process_runnable_tasks

取出队列中的任务,调用process_stream函数处理,返回之后重新将task放入等待队列
主要任务

  • 根据预设的规则设置一个backend
    process_switching_rules -> stream_set_backend
  • 根据相应的调度算法,选择后端服务器,并添加到队列中
    sess_prepare_conn_req -> srv_redispatch_connect -> assign_server_and_queue -> assign_server -> chash_get_next_server
  • 后端服务器请求已满,添加到proxy队列
    pendconn_add

signal_process_queue

自身实现的信号处理机制,接收到信号之后输出到队列,然后在处理信号队列,保证所有请求处理完之后再关闭

wake_expired_tasks

唤醒超时任务,队列分为run queue/wait queue,该函数就是检查wait queue任务,并将其输出到run queue中,以便后续处理。

cur_poller.poll

获取所有活动的fd,并将其更新到cache中

主要函数

  • _do_poll
    • epoll_wait
    • fd_may_recv
    • fd_may_send
      • fd_update_cache

fd_process_cached_events

处理fd事件,建立连接、数据收发等

主要函数

  • conn_fd_handler
    • si_conn_recv_cb
      • raw_sock_to_pipe/ssl_sock_to_buf
      • raw_sock_to_buf
    • si_conn_send_cb