为了让集群中每个实例都知道其他实例的状态信息,实例之间会按照一定规则进行通信。这个规则就是Gossip协议。
Gossip工作原理可以概括为以下两点:
1.每个集群实例之间会按照一定频率,从集群中挑选一些实例,把ping消息发送给挑选出来的这些实例,用来检测这些实例是否在线,并交换彼此的状态信息。然后实例会返回PONG消息
我们可以直观的看到:实例间使用Gossip协议进行通信时,通信开销受到通信消息大小和通信频率的影响。
Gossip消息大小
ping消息是由clusterMsgDataGossip结构体组成,以下就是clusterMsgDataGossip结构体内容:
typedef struct {
char nodename[CLUSTER_NAMELEN]; //40字节
uint32_t ping_sent; //4字节
uint32_t pong_received; //4字节
char ip[NET_IP_STR_LEN]; //46字节
uint16_t port; //2字节
uint16_t cport; //2字节
uint16_t flags; //2字节
uint32_t notused1; //4字节
} clusterMsgDataGossip;
每个实例在发送一个Gossip消息时,除了会传递自身信息外还会包含集群十分之一实例的状态信息。
如果是1000个实例节点,ping和pong消息加起来就有24KB。并且每个实例都要给其他实例发送PING/PONG消息,这会占据集群的一大部分网络资源。
实例间通信频率
实例间发送消息的频率有两个:
1.每个实例每一秒发送一条PING消息。
2.每个实例每100毫秒会做一次检测,给PONG消息接收超过cluster-node-timeout/2的节点发送PING消息。
单实例每秒发送实例的次数:
PING消息发送数量 = 1 + 10 * 实例数(最近一次接收PONG消息的时间超出cluster-node-timeout/2)
如何降低实例间的带宽开销?
通过调整cluster-node-timeout的大小,多大算合适呢?
你可以通过调整cluster-node-timeout值的前后,使用tcpdump命令抓取实例发送心跳包的网络情况。
通过分析网络包的数量和大小,就可以判断调整cluster-node-timeout值前后,心跳消息占用带宽的情况了。