一、调整内核参数
CONFIG_IP_VS_TAB_BITS
1.1 CONFIG_IP_VS_TAB_BITS说明
IPVS connection hash table size,取值范围:[12,20]。该表用于记录每个进来的连接及路由去向的信息。连接的Hash表要容纳几百万个并发连接,任何一个报文到达都需要查找连接Hash表。Hash表的查找复杂度为O(n/m),其中n为Hash表中对象的个数,m为Hash表的桶个数。当对象在Hash表中均匀分布和Hash表的桶个数与对象个数一样多时,Hash表的查找复杂度可以接近O(1)。
连接跟踪表中,每行称为一个hash bucket(hash桶),桶的个数是一个固定的值CONFIG_IP_VS_TAB_BITS,默认为12(2的12次方,4096)。这个值可以调整,该值的大小应该在 8 到 20 之间,详细的调整方法见后面。每一行都是一个链表结构,包含N列(即N条连接记录),这个N是无限的,N的数量决定了决定了查找的速度。在LVS的实现说明中,有这样的一段话,可以帮助很好的理解行和列的关系:
为了评价Hash函数的效率,我们从一个运行IPVS的真实站点上取当前连接的样本,它一共含有35652个并发连接。在有64K桶的Hash表中,连接分布如下:
桶的长度(Lj)该长度桶的个数(Nj)
5 16
4 126
3 980
2 5614
1 20900
所有连接查找一次的代价为45122,每个连接查找的平均代价为1.266(即45122/35652)。
LVS的调优建议将hash table的值设置为不低于并发连接数。例如,并发连接数为200,Persistent时间为200S,那么hash桶的个数应设置为尽可能接近200x200=40000,2的15次方为32768就可以了。当ip_vs_conn_tab_bits=20 时,哈希表的的大小(条目)为 pow(2,20),即 1048576,对于64位系统,IPVS占用大概16M内存,可以通过demsg看到:IPVS: Connection hash table configured (size=1048576, memory=16384Kbytes)。对于现在的服务器来说,这样的内存占用不是问题。所以直接设置为20即可。
关于最大“连接数限制”:这里的hash桶的个数,并不是LVS最大连接数限制。LVS使用哈希链表解决“哈希冲突”,当连接数大于这个值时,必然会出现哈稀冲突,会(稍微)降低性能,但是并不对在功能上对LVS造成影响。
1.2 调整 ip_vs_conn_tab_bits的方法:
新的IPVS代码,允许调整 ip_vs_conn_bits 的值。而老的IPVS代码则需要通过重新编译来调整。
在发行版里,IPVS通常是以模块的形式编译的。
确认能否调整使用命令 modinfo -p ip_vs(查看 ip_vs 模块的参数),看有没有 conn_tab_bits 参数可用。假如可以用,那么说时可以调整,调整方法是加载时通过设置 conn_tab_bits参数:
在/etc/modprobe.d/目录下添加文件ip_vs.conf,内容为:
options ip_vs conn_tab_bits=20
查看
ipvsadm -l
如果显示IP Virtual Server version 1.2.1 (size=4096),则前面加的参数没有生效
modprobe -r ip_vs
modprobe ip_vs
重新查看
IP Virtual Server version 1.2.1 (size=1048576)
查看内容占用 (约16M)
dmesg |grep IPVS
[root@BJ ~]# dmesg |grep IPVS
IPVS: Registered protocols (TCP, UDP, SCTP, AH, ESP)
IPVS: Connection hash table configured (size=1048576, memory=16384Kbytes)
假如没有 conn_tab_bits 参数可用,则需要重新调整编译选项,重新编译。
Centos6.2,内核版本2.6.32-220.13.1.el6.x86_64,仍然不支持这个参数,只能自定义编译了。
另外,假如IPVS支持调整 ip_vs_conn_tab_bits,而又将IPVS集成进了内核,那么只能通过重启,向内核传递参数来调整了。在引导程序的 kernel 相关的配置行上,添加:ip_vs.conn_tab_bits=20 ,然后,重启。
或者重新编译内核。
二、系统参数优化
2.1 关闭网卡LRO和GRO
现在大多数网卡都具有LRO/GRO功能,即 网卡收包时将同一流的小包合并成大包 (tcpdump抓包可以看到>MTU 1500bytes的数据包)交给 内核协议栈;LVS内核模块在处理>MTU的数据包时,会丢弃;
因此,如果我们用LVS来传输大文件,很容易出现丢包,传输速度慢;
解决方法,关闭LRO/GRO功能,命令:
ethtool -k eth0 查看LRO/GRO当前是否打开
ethtool -K eth0 lro off 关闭GRO
ethtool -K eth0 gro off 关闭GRO
2.2 禁用ARP,增大backlog并发数
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
net.core.netdev_max_backlog = 500000
三、lvs自身配置调优
3.1 尽量避免sh算法
一些业务为了支持会话保持,选择SH调度算法,以实现 同一源ip的请求调度到同一台RS上;但 SH算法本省没有实现一致性hash,一旦一台RS down,当前所有连接都会断掉;如果配置了inhibit_on_failure,那就更悲剧了,调度到该RS上的流量会一直损失;
实际线上使用时,如需 会话保持,建议配置 persistence_timeout参数,保证一段时间同一源ip的请求到同一RS上。
3.2 增大hash桶锁个数
对于一个16核的服务器来说,可以将桶锁个数调整为8.
ipvs源码目录下,修改文件vim ip_vs_conn.c - #define CT_LOCKARRAY_BITS 8;
参考:
http://blog.csdn.net/yanziguishi/article/details/7284793
http://blog.sina.com.cn/s/blog_781b0c850101ogne.html