2013-06-20 55 views
1

我在使PHP尊重啓用RoundRobin的DNS條目方面存在問題。該條目(比如說它是domain.example.com)有三個可能的IP地址分配。 RoundRobin的工作原理(使用ping,telnet,wget等進行測試)。 不幸的是,當使用PHP SOAP擴展,甚至是純文件file_get_contents時,它總是連接到DNS中指定的第一個IP地址。令人驚訝的是,gethostbyname函數看到RoundRobin完美無缺。我已經把一個文件中的每個服務器outputing 1或2或3,另一臺服務器上執行腳本幾次:PHP不尊重DNS中的RoundRobin

var_dump(file_get_contents('http://domain.example.com/test.html')); 
var_dump(gethostbyname('domain.example.com')); 

第一行始終打印「1」(從第一個IP地址)。第二行隨機輸出三個可能的IP地址之一。

問題:有沒有人有類似的問題?如何強制PHP尊重DNS中的RoundRobin,至少在發出SOAP請求時?

編輯 沒有DNS緩存存在,也沒有代理。如前所述,ping,telnet,wget等可以在測試腳本所在的同一臺服務器上正常工作。

+0

難道它之間有一個網絡代理? – mbs

+1

緩存DNS查找。你必須清空系統的DNS緩存。 – Fracsi

回答

1

我們最近遇到了類似於您的問題。我們發現file_get_contents()最終調用getaddrinfo(),它實現RFC3484的一些排序算法。

php source code

PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, zend_string **error_string) 
{ 
    // skip... 

    if ((n = getaddrinfo(host, NULL, &hints, &res))) { 
     if (error_string) { 
      *error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n)); 
      php_error_docref(NULL, E_WARNING, "%s",  ZSTR_VAL(*error_string)); 
     } else { 
      php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n)); 
     } 
    return 0; 
    } 

    //skip... 
} 

這件作品片段的我們仍然搞清楚什麼是更好的方法來處理這個問題。

編輯:

RFC3484的第6節指定目標地址選擇算法,以及第9條有關的IPv4。

規則9:使用最長的匹配前綴。

當DA和DB屬於同一地址族(均爲IPv6或 都是IPv4)的:如果CommonPrefixLen(DA,來源(DA))> CommonPrefixLen(DB,來源(DB)),然後喜歡DA 。類似地,如果CommonPrefixLen(DA,Source(DA))< CommonPrefixLen(DB,Source(DB)), 則優選DB。

假設我們擁有源地址192.168.1.100/24和四個候選目的地地址192.168.1.33/24192.168.1.44/24192.168.2.55/24192.168.2.66/24

以二進制格式

S 192.168.1.100 11000000.10101000.00000001.01100100 
------------------------------------------------------- 
DA 192.168.1.33  11000000.10101000.00000001.00100001 
DB 192.168.1.44  11000000.10101000.00000001.00101100 
DC 192.168.2.55  11000000.10101000.00000010.00110111 
DD 192.168.2.66  11000000.10101000.00000010.01000010 

表示上述地址你可以看到,

CommonPrefixLen(DA, S) == CommonPrefixLen(DB, S) == 25 > 
CommonPrefixLen(DC, S) == CommonPrefixLen(DD, S) == 22 

所以DADB,以先到者爲準在原來的DNS查詢,將被選爲最終目的地glibc執行。

+0

感謝您的調查。你當然是對的。有在這方面的一些爭論[Debian錯誤跟蹤器(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=438179),當源和目的地地址是在不同的子網此排序行爲被禁用。我已經在Debian機器上檢查過(使用glibc 2.19)和RoundRobin。不幸的是不能在CentOS 7.1上使用glibc 2.17,但我可以忍受這一點。 – Furgas