公司的一业务使用的是长连接的tcp协议(就算在没有业务数据包交互的情况下, 每隔n秒c/s间都会有keepalive包传递), 使用lvs作接入层的负载均衡, ld通过heartbeat做双机热备, 主备ld之间因为只涉及到公网ip的漂移, 所以没有使用ldirectd来重构ipvs表, 而是直接使用自己写的脚本来重构备机上的ipvs表。 所以haresoucre的配置很简单:master_node_name public_ip ipvs_shell。
在实际的运营过程中, 由于是长连接业务, 且为了保证更好的用户体验, 我们决定把主备ld之间的状态同步也加上, 所谓的状态同步, 就是ld会维护一张连接跟踪表(connection tracking table), 把每个连接的实时状态都保存在这张表里面。 要做到主备ld之间的这张连接跟踪表的同步, 需要在主备ld上分别启动一个内核守护线程, 通过广播的方式来同步数据。
主ld:
ipvsadm --start-daemon=master --mcast-interface=eth1
备ld:
ipvsadm --start-daemon=backup --mcast-interface=eth1
在主备ld上分别执行这两个命令后, 可以在发现备ld上有个224.0.0.81:8848 listen的内核守护线程, 用来接收从主ld发过来的广播包。 所以, 要记得把防火墙的udp协议的8848端口打开, 不然同步不了, 可以在备ld上通过ipvsadm -Lnc看是否有连接同步过来。
另外, 在实际的运营过程中还发现, 主备ld之间是怎么触发这种同步的呢?
一是新的连接, 不管怎么样, 都会同步过去,
二是对于已经存在的连接, 如果有足够的数据量在这个连接上传送, 在备ld上的expire time即将到期/或者已经到期的时候, 主ld会把这份已经存在的连接再次同步到备ld
另外的是, 一个老的连接, 一直存在, 但是备机上的expire time已经到期了(主备上的expire time分别有主备机维护)还发现跟这个连接上的传递数据量有关系(就是要数据量要达到一定的阀值, 才会触发), 如果c/s之间一直没有业务数据, 仅仅只有每n秒传递的心跳数据(也就是说没有达到触发的阀值), 会发现备ld上的连接跟踪表里已经没有这份数据。
在正常业务数据的情况:
idle的情况(只有keepalive包)