unbound原始碼分析
版本: 1.17.2
編譯選項:
./configure --prefix=your_path --enable-subnet --enable-debug --with-libevent
請求呼叫棧:
看了worker_handle_request的原始碼,unbound也是存在ip維度的限速的。
dig qq.com @127.0.0.1
worker_init
初始化執行緒變數worker
在comm_base_set_slow_accept_handlers方法中傳入worker_stop_accept和worker_start_accept函式指標以及worker,並設定到worker->base->stop_accept和worker->base->start_accept,worker->base->cb_arg。
在呼叫accpet相關函式指標時,就會傳入worker->base->cb_arg。
設定worker->comsig的訊號回撥函式為worker_sighandler。處理訊號為SIGHUP
、SIGINT
、SIGQUIT
、SIGTERM
。
設定worker->front為listen_create返回值(接收使用者請求),主要回撥方法是worker_handle_request
。
回撥方法原型:typedef int comm_point_callback_type(struct comm_point*, void*, int, struct comm_reply*);
unbound使用struct comm_point來表示一個監聽的socket。
- tcp型別的comm_point建立透過
comm_point_create_tcp
方法。其accept回撥為comm_point_tcp_accept_callback
。 - udp型別的comm_point建立透過
comm_point_create_udp
方法。其回撥為comm_point_udp_ancil_callback
。
unbound worker透過worker_handle_control_cmd來執行命令控制。
每個worker裡面存在back欄位來向權威伺服器發起遞迴,主要是在worker_init
方法中呼叫outside_network_create
方法來初始化。
unbound的lruhash資料結構:動態增長的雜湊表(當元素數量等於陣列長度時,擴容為原來的2倍),採用lru機制來限制雜湊表的記憶體使用量,當超過最大記憶體使用量時淘汰最少使用的元素。(原理跟java中的linkedhashmap差不多)
slabhash則是對lruhash進行一層封裝,內部用陣列存放多個lruhash,再進行一層hash,把資料分散到不同lruhash中。
unbound的region資料結構:記憶體分配緩衝區,分配的記憶體大於large_object_size
時,就呼叫malloc方法分配記憶體,然後用large_list
儲存為單連結串列節點,如果當前需要的記憶體大小大於available
時,就malloc分配一塊8192位元組大小的記憶體塊,然後用next
儲存為單連結串列節點,使用data
儲存當前分配的記憶體塊,然後從記憶體塊中劃分一塊記憶體出去。
unbound接收請求後,最後會儲存為一個mesh事務樹,然後依次呼叫subnet模組查ecs快取、iterator模組發起遞迴請求。(方法mesh_run)
遞迴查詢:iter_operate方法
- process_handle -> iter_handle
- iter_handle -> processInitRequest -> processQueryTargets -> worker_send_query -> outnet_serviced_query -> serviced_create(設定定時器,預設第一次觸發就傳送資料)
- process_response -> iter_handle -> processQueryResponse
超時回撥:serviced_timer_cb、響應回撥:worker_handle_service_reply
選路演算法:
iter_server_selection
第一次傳送資料:
serviced_timer_cb -> serviced_udp_send -> pending_udp_query(建立一個pending_udp_timer_cb的定時器) -> randomize_and_send_udp -> comm_point_send_udp_msg
響應路徑:
comm_point_udp_ancil_callback -> outnet_udp_cb -> serviced_udp_callback -> serviced_callbacks -> worker_handle_service_reply -> mesh_report_reply -> mesh_run -> iter_operate -> process_response -> iter_handle -> processQueryResponse -> processFinished -> mesh_continue -> mesh_query_done -> mesh_send_reply -> comm_point_send_reply