在我们对haproxy1.6.9进行性能测试的时候,为了提升性能,测试出haproxy的极限,我们启用了haproxy不建议使用的多进程(nbproc)。结果遇到了一些比较麻烦的问题,由于haproxy上的统计信息都是存放在stats上,但是stats只能绑定到一个进程上,这就意味着我们无法统计所有负载均衡进程上的信息。
为了解决这个问题,我们尝试过将多个进程的数据流合并到一个用于统计的进程上,但是这种方式无法解决haproxy性能问题(因为最终所有的流都要流向同一个进程)。最后决定通过增大进程可用fd数和开启多线程(nbthread)。
haproxy静态编译概览
为了保证haproxy的稳定性,我们希望系统的变动不会影响到haproxy。我们需要静态编译haproxy。
静态编译haproxy的方式很简单,但是会因为glibc的一些新特性导致无法编译成功,下面是对haproxy不同版本静态编译出现的问题及解决方法:
版本 | 是否支持多线程 | 报错信息 | 解决方法 |
---|---|---|---|
v1.7.0 | 否 | static linked binary use getaddrinfo | recompile glibc with –enable-static-nss |
v1.8.0 | 是 | static linked binary use getaddrinfo | recompile glibc with –enable-static-nss |
v1.9.0 | 是 | static linked binary use getaddrinfo | recompile glibc with –enable-static-nss |
v2.0.0 | 是 | undefined “NSSXXXXX” | recompile glibc with –enable-static-nss –disable-nss-crypt |
v2.1.0 | 是 | undefined “NSSXXXXX” | recompile glibc with –enable-static-nss –disable-nss-crypt |
v2.2.0 | 是 | dynamic STT_GNU_IFUNC symbol strcmp |
unresolved |
master | 是 | dynamic STT_GNU_IFUNC symbol strcmp |
unresolved |
其中v1.7.0~v1.9.0中遇到的问题是由于name service switch
导致的,相关的讨论和解决方法可以参考stackoverflow。
v2.0.0~v2.1.0中遇到的undefined “NSSXXXX”问题同样是由于nss导致的,相关的讨论和解决方法可以参考stackoverflow。
v2.2.0~master中遇到的STT_GNU_IFUNC问题是由于indirect function
导致的,相关的内容可以参考stackoverflow。尝试过重新编译gcc关闭IFUNC等相关特性但是貌似不起作用,该问题目前未能解决。
总的来说glibc-static库存在一些问题,对于一些简单的应用来说静态编译不会遇到阻碍,但是如果是比较复杂且使用了glibc或gcc新特性的应用就会遇到很多问题。
详细步骤
以v2.1.0为例,静态编译haproxy。
-
编译静态openssl:
1
2
3$ wget openssl-OpenSSL_1_1_0g.zip && tar xvf openssl-OpenSSL_1_1_0g.zip $ ./config --prefix=/tmp/staticlibssl -fPIC no-shared $ make install -j 16
-
从
http://vault.centos.org/centos/
下载对应的src.rpm1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39# 解压安装 $ rpm -i http://vault.centos.org/centos/glibc.src.rpm # 修改spec文件,增加--enable-static-nss,替换--enable-nss-crypt为--disable-nss-crypt $ vim glibc.spec ../configure CC="$GCC" CXX="$GXX" CFLAGS="$configure_CFLAGS" \ --prefix=%{_prefix} \ --enable-add-ons=nptl$AddOns \ --with-headers=%{_prefix}/include $EnableKernel \ %ifarch ppc64 --disable-bind-now \ %else --enable-bind-now \ %endif --build=%{target} \ %ifarch %{multiarcharches} --enable-multi-arch \ %endif %ifarch %{elisionarches} --enable-lock-elision=yes \ %endif --enable-obsolete-rpc \ --enable-systemtap \ --enable-static-nss \ ${core_with_options} \ %if %{without werror} --disable-werror \ %endif --disable-profile \ %if %{with bootstrap} --without-selinux \ --disable-nss-crypt || %else --disable-nss-crypt || %endif { cat config.log; false; } # 编译 $ rpmbuild -bb glibc.spec # 安装glibc-static $ rpm --force -i glibc-static-xxxxx.rpm
-
下载haproxy源码,切换到v2.1.0tag:
1
2$ git clone https://github.com/haproxy/haproxy.git $ git checkout v2.1.0
- 修改Makefile文件,删除所有
-Wl,-Bstatic
和-Wl,-Bdynamic
。 -
执行make命令:
1
$ make TARGET=linux-glibc LDFLAGS="--static" USE_OPENSSL=1 SSL_INC=/tmp/staticlibssl/include SSL_LIB=/tmp/staticlibssl/lib USE_THREAD=1 USE_ZLIB=1 USE_STATIC_PCRE=1 USE_LD=1 -j 16
修改/etc/nsswitch.conf
由于在上文中我们使用 --enable-static-nss
选项重新编译了glibc,这个改动导致了在NSS配置/etc/nsswitch.conf
中无法使用compat
字段,只支持的files
和dns
字段。
如果要支持compat
字段,需要打上补丁:
1 |
|
或者更简单粗暴的方法,直接修改/etc/nsswitch.conf
文件,增加files
字段:
1 |
|
参考:https://bugzilla.redhat.com/show_bug.cgi?id=111827