使用gprof工具,可以測出dhcp的性能瓶頸在mdb.c中的lease_enqueue函數。該函數的功能就是維護地址池內部的不同狀態下的地址鏈表,這些鏈表都必須根據時間排序的。目的是每次遍歷都從最老的lease開始。
排序代碼:
/* Insertion sort the lease onto the appropriate queue. */ for (; lp ; lp = lp->next) { if (lp -> sort_time >= comp -> sort_time) break; prev = lp; }
假設,我們配置了一個有幾十萬個IP的地址池,並且這些地址都是可分配的地址。那麼它們都會被放到pool->free的鏈表中,每次維護鏈表進行排序的時候就會耗費很長時間。
很可惜,很多人發現這個問題,並且也反應給isc-dhcp官方,但是貌似沒有得到什麼好的解決辦法。我也折騰了一段時間,偶然想到這些狀態的地址鏈表都是被地址池包含的,如果控制每個地址池內部的地址個數,是不是會有情況?
傳統的dhcpd.conf文件:
subnet 192.0.0.0 mask 192.255.255.255 { option routers 192.0.0.1; default-lease-time 600; max-lease-time 7200; pool { range 192.0.0.1 192.4.255.255 } }
如果這樣配置,分配地址的併發性能只能十幾個每秒。
我把這個大地址池拆分成小地址池,每個小地址池內部包含1024個地址,配置文件改爲:
subnet 192.0.0.0 mask 192.255.255.255 { option routers 192.0.0.1; default-lease-time 600; max-lease-time 7200; pool { range 192.0.0.1 192.0.3.255 } pool { range 192.0.4.0 192.0.7.255 } pool { range 192.0.8.0 192.0.11.255 } …… }
果然,併發性能提高了很多,能達到每秒500個左右。
另外,把lease文件放到共享內存中也能提高不少性能,畢竟對內存的讀寫比硬盤快多了。
(同時也依賴服務器的硬件配置,不過這個影響不是致命的。呵呵……)