2、storage主流程

來源:互聯網
上載者:User

一、概要

用戶端和Storage server主動串連Tracker server。Storage server主動向Tracker server報告其狀態資訊,包括磁碟剩餘空間、檔案同步狀況、檔案上傳下載次數等統計資訊。Storage server會串連叢集中所有的Tracker server,向他們報告自己的狀態。Storage server啟動一個單獨的線程來完成對一台Tracker server的串連和定時報告。需要說明的是,一個組包含的Storage server不是通過設定檔設定的,而是通過Tracker server擷取到的。

不同組的Storage server之間不會相互連信,同組內的Storage server之間會相互串連進行檔案同步。

Storage server採用binlog檔案記錄檔案上傳、刪除等更新操作。binlog中只記錄檔案名稱,不記錄檔案內容。

檔案同步只在同組內的Storage server之間進行,採用push方式,即源頭伺服器同步給目標伺服器。只有源頭資料才需要同步,備份資料並不需要再次同步,否則就構成環路了。

Storage server中由專門的線程根據binlog進行檔案同步。為了最大程度地避免相互影響以及出於系統簡潔性考慮,Storage server對組內除自己以外的每台伺服器都會啟動一個線程來進行檔案同步。

二、storage_func_init

前半部分用於解析設定檔。

//後半部分如下:if ((result=storage_get_my_tracker_client_ip()) != 0) //與各個tracker串連後,調用fdfs_quit(pTServer),然後關閉通訊端(這隻是為了初始化g_tracker_client_ip){return result;}if ((result=storage_check_and_make_data_dirs()) != 0) //解析.data_init_flag檔案,並在data_path檔案夾下建立大量檔案夾。{logCrit("file: "__FILE__", line: %d, " \"storage_check_and_make_data_dirs fail, " \"program exit!", __LINE__);return result;}if ((result=storage_get_params_from_tracker()) != 0) //重建立立串連,向tracker請求TRACKER_PROTO_CMD_STORAGE_PARAMETER_REQ,獲得use_storage_id等多個參數。{return result;}if ((result=tracker_get_my_server_id()) != 0) //設定g_tracker_client_ip{logCrit("file: "__FILE__", line: %d, " \"get my server id from tracker server fail, " \"errno: %d, error info: %s", __LINE__, \result, STRERROR(result));return result;}if (g_use_storage_id) //本例為0{if ((result=fdfs_get_storage_ids_from_tracker_group( \&g_tracker_group)) != 0){return result;}}if ((result=storage_check_ip_changed()) != 0){return result;}if ((result=init_pthread_lock(&sync_stat_file_lock)) != 0){return result;}return storage_open_stat_file();}


三、tracker_sync_init

初始化g_binlog_index和g_binlog_fd。注意:Storage server採用binlog檔案記錄檔案上傳、刪除等更新操作(只記錄檔案名稱,不記錄檔案內容)。


四、tracker_report_init

g_storage_servers和g_sorted_storage清零,初始化reporter_thread_lock。


五、storage_service_init

與tracker_serverce_init類似,free_queue_init;建立四個線程work_thread_entrance(管道可讀事件加入libevent監聽,處理函數為storage_recv_notify_read,並不斷等待),每個線程分配一個storage_nio_thread_data結構體。


六、tracker_report_thread_start
對每一個tracker(儲存在g_tracker_group.servers中),建立一個report線程(處理函數為tracker_report_thread_entrance),以及src_storage_status變數(int)和my_report_status變數(signed char)。

tracker_report_thread_entrance部分代碼如下:

                ......if (tracker_report_join(pTrackerServer, tracker_index, \sync_old_done) != 0)  //向tracker發送TRACKER_PROTO_CMD_STORAGE_JOIN訊息,my_report_status[tracker_index]記錄返回狀態。{sleep(g_heart_beat_interval);continue;}                ......if (!sync_old_done){}src_storage_status[tracker_index] = \tracker_sync_notify(pTrackerServer);//向tracker發送TRACKER_PROTO_CMD_STORAGE_SYNC_NOTIFY。if (src_storage_status[tracker_index] != 0){int k;for (k=0; k<g_tracker_group.server_count; k++){if (src_storage_status[k] != ENOENT){break;}}if (k == g_tracker_group.server_count){ //src storage server already be deletedint my_status;if (tracker_get_storage_max_status( \&g_tracker_group, g_group_name, \g_tracker_client_ip, my_server_id, \&my_status) == 0){tracker_sync_dest_query(pTrackerServer);if(my_status<FDFS_STORAGE_STATUS_OFFLINE&& g_sync_old_done){  //need re-sync old filespthread_mutex_lock( \&reporter_thread_lock);g_sync_old_done = false;sync_old_done = g_sync_old_done;storage_write_to_sync_ini_file();pthread_mutex_unlock( \&reporter_thread_lock);}}}fdfs_quit(pTrackerServer);  //向tracker發送FDFS_PROTO_CMD_QUIT。sleep(g_heart_beat_interval);continue;}sync_time_chg_count = 0;last_df_report_time = 0;last_beat_time = 0;last_sync_report_time = 0;stat_chg_sync_count = 0;last_trunk_file_id = 0;last_trunk_total_free_space = -1;while (g_continue_flag){current_time = g_current_time;if (current_time - last_beat_time >= \g_heart_beat_interval){if (tracker_heart_beat(pTrackerServer, \&stat_chg_sync_count, \&bServerPortChanged) != 0) //發送TRACKER_PROTO_CMD_STORAGE_BEAT至tracker,獲得leader tracker和所有其他tracker的資訊,並更新本地資訊。{break;}if (g_storage_ip_changed_auto_adjust && \tracker_storage_changelog_req( \pTrackerServer) != 0){break;}last_beat_time = current_time;}if (sync_time_chg_count != g_sync_change_count && \current_time - last_sync_report_time >= \g_heart_beat_interval){if (tracker_report_sync_timestamp( \pTrackerServer, &bServerPortChanged)!=0) {break;}sync_time_chg_count = g_sync_change_count;last_sync_report_time = current_time;}if (current_time - last_df_report_time >= \g_stat_report_interval){if (tracker_report_df_stat(pTrackerServer, \&bServerPortChanged) != 0)  //發送TRACKER_PROTO_CMD_STORAGE_REPORT_DISK_USAGE命令。{break;}last_df_report_time = current_time;}if (g_if_trunker_self){if (last_trunk_file_id < g_current_trunk_file_id){if (tracker_report_trunk_fid(pTrackerServer)!=0){break;}last_trunk_file_id = g_current_trunk_file_id;}if (last_trunk_total_free_space != g_trunk_total_free_space){if (tracker_report_trunk_free_space(pTrackerServer)!=0){break;}last_trunk_total_free_space = g_trunk_total_free_space;}}sleep(1);}if ((!g_continue_flag) && fdfs_quit(pTrackerServer) != 0){}close(pTrackerServer->sock);pTrackerServer->sock = -1;if (g_continue_flag){sleep(1);}}if (nContinuousFail > 0){}thracker_report_thread_exit(pTrackerServer);return NULL;}

七、sched_start

產生一個調度線程,調度以下任務:log_sync_func,fdfs_binlog_sync_func,fdfs_stat_file_sync_func,以及可能存在的trunk_binlog_sync_fun,log_sync_func(&g_access_log_contex),log_notify_rotate。


八、storage_dio_init

為每一個store_path(本例的storage只有一個store_path)建立一個讀線程和一個寫線程。線程的處理函數都是dio_thread_entrance。

static void *dio_thread_entrance(void* arg) {int result;struct storage_dio_context *pContext; struct fast_task_info *pTask;pContext = (struct storage_dio_context *)arg; pthread_mutex_lock(&(pContext->lock));while (g_continue_flag){if ((result=pthread_cond_wait(&(pContext->cond), \&(pContext->lock))) != 0)   //等待被喚醒。{}while ((pTask=task_queue_pop(&(pContext->queue))) != NULL){((StorageClientInfo *)pTask->arg)->deal_func(pTask); //處理讀寫任務}}pthread_mutex_unlock(&(pContext->lock));if ((result=pthread_mutex_lock(&g_dio_thread_lock)) != 0){}g_dio_thread_count--;if ((result=pthread_mutex_unlock(&g_dio_thread_lock)) != 0){}return NULL;}

九、storage_accept_loop

監聽是否有串連到來,如果有,則向一個背景工作執行緒發送一個資訊(fast_task_info結構的地址),從而交給背景工作執行緒處理。


十、總結

storage使用4個背景工作執行緒(work_thread_entrance,當管道可讀事件觸發時,調用storage_recv_notify_read),每個tracker一個report線程(tracker_report_thread_entrance),一個調度線程(調度一些同步任務),每個store_path分別一個讀寫線程(dio_thread_entrance)。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.