目录

一、简介

二、HAProxy启动命令及参数选项说明


本文章内容主要参考了HAProxy英文文档管理指南部分,HAProxy版本为2.4.0。

地址为:HAProxy version 2.4.0 - Management Guide

一、简介

HAProxy是一种常见的负载均衡器,支持四层(TCP)和七层(HTTP)负载均衡。目前已经支持多线程,它使用事件多路复用来调度其所有活动,而不依赖于系统调度。

在大多数情况下它作为单进程运行,因此"ps aux"命令将只会输出一个"haproxy"进程,除非正在进行软加载,并且是旧进程与新进程并行完成各自的工作。因此,使用 strace 实用程序会容易追踪其活动。为了根据可用处理器的数量进行扩展,默认情况下,haproxy 将在每个可运行的处理器上启动一个工作线程。除非明确进行不同的配置,不然一般传入的流量都会分配到所有这些线程上,所有线程都运行相同事件循环。要尽可能降低线程间的依赖关系,以便达到接近线性的可扩展性。这会产生一些影响,例如指定的连接会由单个线程提供服务。要保证连接数至少与线程数一样多,才能最大限度发挥处理能力。

HAProxy被设计成在启动时将自己隔离在chroot jail中,此时它不能执行任何文件系统操作。对于它所依赖的库(例如:libc、libssl 等)也是如此。其目的在于使正在运行的进程不能重新加载配置文件来应用更新,而是使用更新后的配置文件启动新进程。其他一些不太明显的影响是 libc 在运行时可能尝试访问的某些时区文件或解析器文件会找不到,尽管这通常不会发生,因为启动后不需要它们。这个原则的一个很好的结果是 HAProxy 进程是完全无状态的,杀掉后不需要清理,所以任何有效的杀进程方法都可以正确杀掉HAProxy进程。

HAProxy不写日志文件,但是它依赖于标准的syslog协议将日志发送到远程服务器(通常位于同一系统上)。

HAProxy 使用其内部时钟来强制超时,这是从系统时间派生来的,不过对意外漂移进行了纠正。这是通过限制 poll() 中等待某个事件所花费的时间,并计算它实际花费的时间来完成的。实际上,等待时间不会超过一秒钟。这就解释了为什么当在一个完全空闲的进程上运行 strace时,poll()(或其任何变体)的周期性调用会被两个 gettimeofday() 调用所包围。这是正常的、完全无害的并且成本很低,它们的负载在系统规模上检测不到。

HAProxy 是 TCP 代理,而非路由器。它处理经过了内核验证的已建立连接,而不使用任何形式的数据包,也没有使用处于其他状态的套接字(例如:没有 SYN_RECV 或 TIME_WAIT)。它依赖于系统来接收传入连接并发起传出连接。这样,在转发连接的两侧数据包之间没有依赖关系,可以是不同的大小、数量等。由于只能从处于 LISTEN 状态的套接字接收连接,因此所有它正在监听的套接字必须使用“netstat”来显示监听套接字。

二、HAProxy启动命令及参数选项说明

通过在命令行上调用带多个参数的HAProxy程序启动HAproxy。语法如下:

haproxy [<options>]*

说明:[<options>]*表示任意数量的可选项,每个选项一般总是以”-”开头。

如果后面不跟任何选项,HAProxy 会显示帮助页面。可用的选项可能会因操作系统不同而略有不同。在配置文件的“global”部分,有相当一部分与之重合。在这种情况下,命令行总是优先于配置文件,这样,命令行可以用来快速执行一些设置,而不用管配置文件里的配置情况。以下是2.4.0的启动选项列表:

-- <cfgfile>*

"--"后可跟多个配置文件或者配置文件的路径,它们会按照声明的顺序加载并处理。

-f <cfgfile|cfgdir>

    将<cfgfile>添加到配置文件列表中进行加载。如果 <cfgdir> 是一个目录,目录下的所有非隐藏的”.cfg”后缀的文件(并且只有文件)会按词法顺序(使用 LC_COLLATE=C)添加到要加载的配置文件列表中。配置文件按其声明顺序加载和处理。也可以多次使用此选项加载多个配置文件。

    “--”和“-f”之间的区别在于每个配置文件前必须有一个“-f”选项,而“--”选项只需要在所有配置文件最前面写一个就行。两个选项也可以一起使用,仍然是按声明的顺序加载和处理。

注意:每个配置文件中的第一个关键字必须是“global”、“defaults”、“peers”、“listen”、“frontend”、“backend”中的一个。如:不能只包含服务器列表。

-C <dir>

在加载配置文件前将配置文件所在目录更改到<dir>。

-D

以守护进程的形式启动HAProxy。fork后进程脱离当前终端,即使配置有问题,终端也不会再报错。相当于配置文件里的“global”区域中的“daemon”关键字。建议始终在任何 init 脚本中都设置为daemon方式启动。这样,即使配置有问题也不会影响到整个系统的启动。

-L <name>

将本地对等名称更改为 <name>,默认为本地主机名。这仅用于对等复制的情形。可以在配置文件中使用变量 $HAPROXY_LOCALPEER 来引用对等名称

-N <limit>

将每个代理的默认最大连接数 maxconn 设置为 <limit> 而不是内置的默认值(通常是 2000)。该选项仅对调试有用。

-V

启用详细模式。与“-q”或"quiet"的效果相反。

-W

以master-worker模式启动。相当于配置里“global”区域中的“master-worker”关键字。

这种模式将启动一个“master”来监控“workers”。使用这种模式,您可以通过向主服务器发送 SIGUSR2 信号来直接重新加载 HAProxy。master-worker 模式与前台或守护进程模式是兼容的。建议在多进程和 systemd 中使用此模式。

-Ws

master-worker 模式,支持 `notify` 类型的 systemd 服务。此选项仅在 HAProxy 构建时启用了 `USE_SYSTEMD` 构建选项时可用。

-c

只检查配置文件并在尝试绑定之前退出。如果一切正常,退出状态为零,如果遇到错误,则退出状态非零。如有警告,将予以报告。相当于启动脚本中的check参数。可参看之前的文章中HAProxy的init脚本相关内容。

-d

启用调试模式。会让进程保持在前端并显示传入和传出事件。不要在 init 脚本中使用它。

-dD

启用诊断模式。此模式下可疑的配置语句将输出额外的警告,这种模式永远不会阻止启动,也不会更改退出状态码。

-dG

使用此选项后getaddrinfo() 不会将主机名解析为地址。当怀疑 getaddrinfo() 没有按预期工作时可以使用它。因为各系统上有许多getaddrinfo() 的虚假实现会导致难以排除故障的异常,使用此选项会很有用。

-dM[<byte>]

强制填充内存,使用 malloc() 或 pool_alloc() 分配每个内存区域时用先将其用 <byte> 填充然后再传递给调用者。当 <byte> 未指定时,默认为 0x50 ('P')。该选项会稍微减缓操作速度,但它有助于可靠地触发因代码中缺少初始化而导致莫名其妙的崩溃问题。请注意,-dM0 具有将任何 malloc() 转换为 calloc() 的效果。在任何情况下,如果使用此选项时某个错误出现或消失,则表示 haproxy 中存在错误。

-dS

该选项会禁用 splice() 系统调用。它相当于“global”区域的“nosplice”关键字。当怀疑 splice() 行为不当或导致性能问题时,或者使用 strace 查看转发的数据(使用 splice() 时不会出现)时,可以使用该选项。

-dV

在服务器端禁用 SSL 验证。它相当于在“global”区域的“ssl-server-verify none”。主要用于生产环境中重现生产问题。该选项会降低服务器的 SSL 安全性,切勿在 init 脚本中使用它。

-dW

设置后,在处理配置时只要有警告,haproxy 都将无法启动。这有助于检测不易察觉的错误并保持配置的整洁和跨版本的可移植性。当配置由人手动管理时,建议在服务脚本中设置此选项,但建议不要在生成的配置中使用它,这往往会发出更多警告。它可能与“-c”结合使用以导致已检查配置中的警告失败。这相当于全局选项“zero-warning”。

-db

此选项禁用后台模式和多进程模式,使用后该进程仍处于前端。它主要用于开发及小型测试期间,使用 Ctrl-C 可以停止该进程。切勿在 init 脚本中使用它。

-de

禁用“epoll”轮询器的使用。它相当于“global”区域的关键字“noepoll”。当怀疑与此轮询器相关的错误时此选项最有用。在支持 epoll 的系统上,通常会回退到“poll”轮询器。

-dk

禁用“kqueue”轮询器的使用。它相当于“global”区域的关键字“nokqueue”。当怀疑与此轮询器相关的错误时此选项最有用。在支持 kqueue 的系统上,通常会回退到“poll”轮询器。

-dp

禁用“poll”轮询器的使用。它相当于“global”区域的关键字“nopoll”。当怀疑与此轮询器相关的错误时,它最有用。在支持轮询的系统上,通常会回退到“select”轮询器,该轮询器不能被禁用,且被限制为 1024 个文件描述符。

-dr

忽略掉服务器地址解析的失败。在生产之外验证配置时,无法访问相同的解析器并且在服务器地址解析上失败是很常见的,这使得测试配置变得困难。此选项只是将“none”方法附加到所有服务器的地址解析方法列表中,以确保即使 libc 无法解析地址,启动序列也不会中断。

-m <limit>

将所有进程的总可分配内存限制为 <limit> 兆字节。这可能会导致某些连接被拒绝或速度缓慢,具体取决于正常操作所需的内存量。这主要用于强制进程在资源有限的情况下工作。需要注意的是,该限制的内存不能在进程间共享,所以在多进程场景下,该值要在fork之前去除global.nbproc。

-n <limit>

将每个进程的连接数限制为 <limit>。这相当于“global”区域的关键字“maxconn”,不过优先于该关键字。这可用于快速强制设置下限以避免在资源有限的系统上出现服务中断。

-p <file>

在启动期间将所有进程的 pid 写入 <file>。这相当于“global”区域的关键字“pidfile”。该文件在进入 chroot jail 之前以及在执行“-C”的 chdir()更改目录之后打开。每个 pid 仅出现在属于自己那一行上。

-q

以静默方式启动。这会在配置解析和启动期间禁用一些信息的输出。它可以与“-c”结合起来使用,检查配置文件是否有效。

-S <bind>[,bind_options...]

在 master-worker 模式下,绑定一个主 CLI,它允许访问每个进程,包括正在运行的或将要结束的进程。出于安全原因,建议将主 CLI 绑定到本地 UNIX 套接字。绑定选项与配置文件中的关键字“bind”相同,监听多个端口时以逗号进行分隔。

 注意:在无损重新加载期间,此套接字不能用于从旧进程检索监听到的套接字。

-sf <pid>*

在启动完成后向旧进程发送“完成”信号(SIGUSR1),旧进程会在完成正在做的事情后退出。<pid> 是要发出信号的 pid 列表(每个参数一个)。该列表以任何以“-”开头的选项结束。如果 pid 列表为空也没关系,可以根据“pidof”或“pgrep”等命令的结果动态来构建它。

-st <pid>*

在启动完成后向旧进程发送“终止”信号(SIGTERM)以立即终止它们而不是完成它们正在做的事情。<pid> 是要发出信号的 pid 列表(每个参数一个)。该列表以任何以“-”开头的选项结束。如果 pid 列表为空也没关系,可以根据“pidof”或“pgrep”等命令的结果动态来构建它。

-v

显示版本和构建日期。

-vv

显示版本、构建选项、库版本和可用的轮询器。

-x <unix_socket>

连接到指定的套接字并尝试从旧进程中检索任何可以监听到的套接字(与-S选项不同),并使用它们而不是绑定新的套接字。这使得在 Linux 上重新加载配置时不会丢失任何新连接。

注意:此选项需要在配置中的stats 套接字上通过使用“expose-fd  listeners”启用该功能,如:

stats socket /var/run/haproxy.sock mode 600 expose-fd listeners level user

使用expose-fd listeners及-x选项之后,reload haproxy的时候,会将已建立的TCP连接(TCP套接字)转移到Unix Domain状态套接字中进行处理。

Restart(相当于-st)会直接关掉旧进程并建立新进程,所以会丢弃大量已建立的连接。

而reload(相当于-sf)也会启动新进程,不过旧进程会先处理完当前已建立的连接后再关闭。但是,reload仍然会丢弃极少量的连接,虽然可以满足大多数情形,但是在极其严格的环境下,也是不允许的。

所以在极其严格的环境建议使用配置expose-fd listeners及使用-x选项进行启动。

一般通过init文件,以守护进程的方式启动HaProxy。将现有的pid存储到指定的pid文件,旧进程继续使用原来的pid并在处理完之前的连接以后关闭。类似如下这样:

haproxy -f /etc/haproxy.cfg \

           -D -p /var/run/haproxy.pid -sf $(cat /var/run/haproxy.pid)