1

RoundRobin 対応の DNS エントリを尊重するように PHP を作成することに問題があります。エントリ (たとえば、domain.example.com だとします) には、3 つの可能な IP アドレスが割り当てられています。RoundRobin は動作します (ping、telnet、wget などでテスト済み)。残念ながら、PHP の SOAP 拡張機能を使用すると、プレーンな file_get_contents であっても、常に DNS で指定された最初の IP アドレスに接続されます。驚いたことに、gethostbyname 関数は、RoundRobin が完全に正常であることを認識しています。各サーバーに 1 または 2 または 3 を出力するファイルを配置し、別のサーバーでスクリプトを数回実行しました。

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

最初の行は常に「1」を出力します (最初の IP アドレスから)。2 行目は、3 つの可能な IP アドレスのうちの 1 つをランダムに出力します。

質問: 誰かが同様の問題を抱えていましたか? 少なくともSOAPリクエストを作成するときに、DNSでRoundRobinを尊重するようにPHPに強制するにはどうすればよいですか?

EDIT DNSキャッシュは存在せず、プロキシもありません。前述のように、ping、telnet、wget などは、テスト スクリプトが配置されているサーバーと同じサーバーで問題なく動作します。

4

1 に答える 1

1

最近、あなたと同様の問題が発生しました。最終的に、 RFC3484のソート アルゴリズムを実装する をfile_get_contents()呼び出すことがわかりました。getaddrinfo()

PHPソースコードのスニペット

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, Source(DA)) > CommonPrefixLen(DB, Source(DB)) の場合、DA を優先します。同様に、CommonPrefixLen(DA, Source(DA)) < CommonPrefixLen(DB, Source(DB)) の場合、DB を優先します。

送信元アドレス192.168.1.100/24と 4 つの候補宛先アドレス192.168.1.33/24, 192.168.1.44/24,192.168.2.55/24があるとし192.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

SoDAまたはDBのうち、元の DNS クエリで最初に来る方が、glibc実装の最終的な宛先として選択されます。

于 2015-10-23T07:21:28.623 に答える