概述:
(1)每个tracker服务在启动时会调用tracker_relationship_init函数启动一个线程relationship_thread_entrance。该线程会每隔几秒进行各个tracker的关系确认,若leader发生了变动,或宕机之类,会重新选出leader。
(2) 调用流程
main函数
|-int tracker_relationship_init()
创建线程
if ((result=pthread_create(&tid, &thread_attr, \
relationship_thread_entrance, NULL)) != 0)
//调用选主流程
|--static int relationship_select_leader()
|--循环遍历 g_tracker_servers.servers
tracker_mem_get_status 获取状态。//协议请求 TRACKER_PROTO_CMD_TRACKER_GET_STATUS
qsort(trackerStatus, count, sizeof(TrackerRunningStatus), \ // 进行排序
relationship_cmp_tracker_status);
//通知如果是自己,
static int relationship_notify_leader_changed(ConnectionInfo *pLeader)
|--relationship_notify_next_leader//循环遍历通知发送TRACKER_PROTO_CMD_TRACKER_NOTIFY_NEXT_LEADER 66协议
|--relationship_commit_next_leader //循环遍历提交TRACKER_PROTO_CMD_TRACKER_COMMIT_NEXT_LEADER 67协议
(3) 选主流程
relationship_select_leader()函数
a) 会调用tracker_mem_get_status()函数进行选主的操作。
b) tracker_mem_get_status函数先会遍历所有的tracker服务器结构,向所有的tracker服务器发起tcp连接,并发送
TRACKER_PROTO_CMD_TRACKER_GET_STATUS命令来获取各个tracker服务器的状态,各个tracker服务器接收到该命令后,会发送自己的状态给该函数(包括该tracker服务器是否是leader的信息),该函数把信息保存到tracker服务器对应的数据结构中。
c) 接下来该函数对各个tracker服务器的状态进行排序(qsort,默认是升序排列),先按照是否是leader进行排序,其次根据运行时间,再次间隔时间,端口等。
d) 排序后的数组的最后一个成员就是leader,取出leader的状态。
e) 若leader是自己,用relationship_notify_leader_changed函数通知各个tracker服务器,若不是自己,把leader的值设置成选出的leader的值。
(4) 选出leader后的通知流程
函数调用关系如下:
relationship_notify_leader_changed()
->relationship_notify_next_leader
->relationship_commit_next_leader()
若tracker的leader已经改变了,就要调用relationship_notify_leader_changed函数对各个tracker进行通知,该函数又继续调用relationship_notify_next_leader和relationship_commit_next_leader函数,下面分别看看这两个函数做了什么。
relationship_commit_next_leader():
(1) 调用do_notify_leader_changed函数发送TRACKER_PROTO_CMD_TRACKER_NOTIFY_NEXT_LEADER命令给tracker服务器。
tracker服务器端收到给命令后,调用tracker_deal_notify_next_leader()函数处理相应的请求。
relationship_commit_next_leader():
(1) 调用do_notify_leader_changed函数发送TRACKER_PROTO_CMD_TRACKER_COMMIT_NEXT_LEADER命令给tracker服务器。
tracker服务器接收到该命令请求后,调用tracker_deal_commit_next_leader()函数处理相应请求。