【DNS】调用方通过DNS轮询、请求重试,实现故障转移高可用

2024-08-31  本文已影响0人  Bogon

一、 实验环境的DNS 配置

DNS 服务端

# systemctl  status  named

# cat /var/named/example.com

; Hash: edfbb39e6e6e531e3294cf74d8018973 1692864498
; Zone file for example.com
;
; Ansible managed
;

$ORIGIN example.com.
$TTL 20

@ IN SOA ns1.example.com. admin.example.com. (
  1692864498
  1H
  5M
  1W
  10M )

                     IN  NS     ns1.example.com.



www                 IN  A      192.168.1.110
www                 IN  A      192.168.1.120
ns1                 IN  A      192.168.1.105

DNS 客户端

# cat  /etc/resolv.conf

nameserver   192.168.1.105

二、 客户端测试

客户端服务器上配置的nameserver 将www.example.com 解析在 192.168.1.110 和 192.168.1.120

在服务器上执行curl操作:

# curl   -vvv  http://www.example.com/api

Trying 192.168.1.110:80...
connect to 192.168.1.110 port 80 failed: connection refused

Trying 192.168.1.120:80...Connected to www.example.com(192.168.1.120) port 80 
GET /api HTTP/1.1
Host: www.example.comUser.Agent: curl/7.79.1
Accept: */*
Mark bundle as not supporting multiuseHTP/1.1 302 Found
Server: nginx/1.17.10
Date: sat, 31 Aug 2024 13:19:08 CMTcontent-Length:0
Connection: keep-aliveLocation: http://www.example.com/api/
Connection #o to host www.example.com left intact

对curl的输出做一个解读

根据您提供的信息,我们可以详细解读一下 curl 操作的结果:

解析与连接

  1. DNS 解析

    • www.example.com 被解析为两个 IP 地址:192.168.1.110192.168.1.120
  2. curl 请求的执行

    • curl 首先尝试连接到 192.168.1.110 的端口 80。结果显示连接被拒绝(connection refused),这通常意味着该服务器上的端口 80 没有在监听,或者防火墙阻止了访问。
    • 接着,curl 尝试连接到 192.168.1.120 的端口 80,这次连接成功了。

curl 输出的详细信息

  1. 连接成功

    • Connected to www.example.com (192.168.1.120) port 80 (HTTP/1.1)
  2. 请求发送

    • GET //api HTTP/1.1:请求路径为 //api
    • Host: www.example.com:设置请求的主机头。
  3. 响应

    • HTTP/1.1 302 Found:服务器返回了一个 302 重定向响应。这表示请求的资源已经被临时移动到其他位置。
    • Location: http://www.example.com//api/:重定向的目标 URL 地址是 http://www.example.com//api/
  4. 其他头部信息

    • Server: nginx/1.17.10:响应来自 nginx 服务器,版本为 1.17.10。
    • Date: Sat, 31 Aug 2024 13:19:08 CMT:响应的日期和时间。
    • Content-Length: 0:响应体的长度为 0 字节,因为重定向响应没有内容。
    • Connection: keep-alive:连接保持活动状态,允许后续请求使用相同的连接。

总结

如果您想要正确访问资源,您需要检查并确保服务器 192.168.1.110 的端口 80 可用,并可能需要处理重定向以访问正确的 URL。如果重定向是预期的行为,那么您应该将请求发送到新的 URL 地址。

对curl 表现出的重试机制做一个解读

curl 的重试机制可以归因于以下几个方面,主要涉及其连接和请求处理流程:

1. DNS 轮询

curl 在发起请求时会尝试使用 DNS 解析得到的 IP 地址列表中的多个地址。这是为了提高可靠性,确保即使某些 IP 地址不可用,curl 也能继续尝试其他地址。这种机制称为 DNS 轮询。

在您的例子中,curl 首先尝试连接到 72.16.211.27,当连接失败时,它会继续尝试其他 IP 地址 72.16.211.50。这是 curl 默认的行为,用于提高网络请求的成功率。

2. 连接管理

3. HTTP 重定向

curl 也处理 HTTP 重定向(3xx 响应状态码)。默认情况下,curl 会处理最多 50 次重定向(可以通过 --max-redirs 选项调整)。在您的例子中,服务器返回了 302 重定向,curl 自动处理了重定向并显示了新的目标 URL。

4. 连接保持(Keep-Alive)

curlConnection: keep-alive 头部表明服务器希望保持连接活跃,以便后续请求可以使用相同的连接。虽然在您的情况中,这个头部主要影响了连接的持久性,但也与请求的处理和重试逻辑有关。

实际操作中的机制

示例:设置重试

如果希望使用 curl 设置重试,可以使用以下选项:

curl --retry 5 http://example.com

这会在请求失败时最多重试 5 次。

总的来说,curl 的重试机制通过 DNS 轮询和对连接失败的处理,确保了请求的鲁棒性和成功率。
如果要深入了解 curl 的更多详细选项和机制,可以查阅 curl 的官方文档

如果java代码要实现类似的重试,是否有现成的轮子可以使用?

curl 的重试机制涉及多个底层组件,包括 DNS 轮询和连接重试。了解这些机制的实现方式可以帮助我们在 Java 中实现类似的功能。下面是对 curl 底层机制的详细解释以及 Java 中相似功能的实现方法。

curl 的底层实现

1. DNS 轮询

curl 使用系统提供的 DNS 解析功能来获取域名对应的多个 IP 地址。curl 会尝试这些 IP 地址中的每一个,直到找到一个可以成功连接的地址。

2. 连接失败处理

curl 连接失败时,它可以尝试以下几种处理方法:

在 Java 中实现类似功能

在 Java 中实现类似的 DNS 轮询和连接重试功能,可以利用现有的库和框架。以下是一些常见的实现方法:

1. 使用现有的库

2. 自定义实现

如果需要更细粒度的控制,可以自定义实现 DNS 轮询和重试机制。以下是一个简单示例,展示如何在 Java 中实现基础的 DNS 轮询和连接重试:

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;

public class CustomHttpClient {
    private static final int MAX_RETRIES = 3;
    private static final int TIMEOUT = 5000; // 5 seconds

    public static void main(String[] args) {
        String domain = "example.com";
        List<String> ipAddresses = getIpAddresses(domain);
        String endpoint = "/opentalk";

        for (String ip : ipAddresses) {
            String url = "http://" + ip + endpoint;
            for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
                try {
                    HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
                    connection.setConnectTimeout(TIMEOUT);
                    connection.setReadTimeout(TIMEOUT);
                    connection.setRequestMethod("GET");

                    int responseCode = connection.getResponseCode();
                    System.out.println("Response Code: " + responseCode);
                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        // Process response
                        break; // Exit retry loop on success
                    }
                } catch (IOException e) {
                    System.err.println("Connection failed for IP: " + ip + " on attempt " + (attempt + 1));
                    if (attempt == MAX_RETRIES - 1) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private static List<String> getIpAddresses(String domain) {
        List<String> ipAddresses = new ArrayList<>();
        try {
            InetAddress[] inetAddresses = InetAddress.getAllByName(domain);
            for (InetAddress inetAddress : inetAddresses) {
                ipAddresses.add(inetAddress.getHostAddress());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ipAddresses;
    }
}

总结

根据需求选择适合的库或自定义实现方式,可以有效地处理网络请求的重试和容错机制。

curl 的重试机制,有哪些参考文档可以提供一下?

对于了解 curl 的重试机制及其底层实现,以下是一些有用的参考文档和资源,它们详细介绍了 curl 的工作原理、底层组件和相关配置:

官方文档与资源

  1. curl 官方文档

    • curl 的官方文档提供了关于命令行选项、重试机制以及如何配置 curl 的详细信息。
    • curl Manual
    • curl Options — 详细介绍了 curl 支持的各种选项,包括重试和超时设置。
  2. libcurl 文档

    • libcurlcurl 的底层库,文档详细描述了其 API 和实现细节,适合需要深入理解 curl 内部工作机制的开发者。
    • libcurl Documentationlibcurl 的官方文档,涵盖了 API 函数和使用示例。
    • libcurl FAQ — 常见问题解答,涉及常见的使用问题和解决方案。
  3. curl 源代码

    • curl 的源代码可以为理解其重试机制和 DNS 轮询实现提供直接的视角。
    • curl GitHub Repositorycurl 的 GitHub 仓库,其中包含源代码和开发历史。
  4. curl 的 Retry 选项

    • curl 支持的重试选项和如何使用它们的具体说明。
    • Retry Options in curl — 关于 curl--retry 选项的官方说明。

其他参考资源

  1. RFC 文档

  2. 技术博客和文章

    • 许多技术博客和文章讨论了 curl 的使用技巧和底层实现。例如:
  3. 网络编程书籍

实践和实验

结合上述资源,您可以深入了解 curl 的重试机制、底层实现以及如何在不同的场景中应用和配置 curl

三、参考

libcurl对域名含有多个ip时的超时重试策略
https://xiaochai.github.io/2018/09/11/libcurl-connection-timeout-policy/

DNS Bind服务配置解析
https://www.cnblogs.com/saneri/p/8038070.html

在 BIND DNS 服务器中配置区
https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/9/html/managing_networking_infrastructure_services/assembly_configuring-zones-on-a-bind-dns-server_assembly_setting-up-and-configuring-a-bind-dns-server

上一篇 下一篇

猜你喜欢

热点阅读