繁体   English   中英

在 python requests 库中使用 SRV DNS 记录

[英]Using SRV DNS records with the python requests library

是否可以让 Python requests 库使用 SRV 记录解析领事域名并在发出请求时使用正确的 IP 地址和端口?

例如,假设我在端口 8080 上使用 IP 地址 172.18.0.5 运行 serviceA,并且此服务已向 consul 注册。 鉴于主机的 DNS 设置为使用 consul 来解析查询。 我可以提出以下请求:

requests.get('http://serviceA.service.consul')

并使其等同于请求:

requests.get('http://172.18.0.5:8080')

我最终为使用此答案执行此操作的请求编写了一个补丁。 由于请求库的更新,我不得不进行一些更改。 此补丁适用于请求版本 2.11.1。

我使用 dnspython 库来解析 SRV 记录,它期望 consul 侦听 DNS 请求的 IP 地址和端口可用作环境变量 CONSUL_DNS_IP_PORT。 要使用补丁, requests_use_srv_records从补丁所在的任何模块导入requests_use_srv_records函数,然后调用它。 它只会尝试对以.service.consul结尾的主机使用 consul SRV 记录,其他主机将定期解析。

这是补丁:

# Python Imports
import os
from socket import error as SocketError, timeout as SocketTimeout

# 3rd Party Imports
from dns import resolver
from requests.packages.urllib3.connection import HTTPConnection
from requests.packages.urllib3.exceptions import (NewConnectionError,
                                                  ConnectTimeoutError)
from requests.packages.urllib3.util import connection

def resolve_srv_record(host):

    consul_dns_ip_port = os.environ.get('CONSUL_DNS_IP_PORT', 
                                        '172.17.0.1:53')
    consul_dns_ip, consul_dns_port = consul_dns_ip_port.split(':')

    res = resolver.Resolver()
    res.port = consul_dns_port
    res.nameservers = [consul_dns_ip]

    ans = resolver.query(host, 'SRV')

    return ans.response.additional[0].items[0].address, ans[0].port

def patched_new_conn(self):

    if self.host.endswith('.service.consul'):
        hostname, port = resolve_srv_record(self.host)
    else:
        hostname = self.host
        port = self.port

    extra_kw = {}

    if self.source_address:
        extra_kw['source_address'] = self.source_address

    if self.socket_options:
        extra_kw['socket_options'] = self.socket_options

    try:
        conn = connection.create_connection((hostname, port),
                                            self.timeout,
                                            **extra_kw)

    except SocketTimeout as e:
        raise ConnectTimeoutError(
            self, "Connection to %s timed out. (connect timeout=%s)" %
            (self.host, self.timeout))

    except SocketError as e:
        raise NewConnectionError(
            self, "Failed to establish a new connection: %s" % e)

    return conn

def requests_use_srv_records():
    HTTPConnection._new_conn = patched_new_conn

不,除非你重写requests否则你不能。

SRV 记录旨在查找服务。
在这种情况下,您已经指示使用 http。 所以客户端只会查询serviceA.service.consul A 或 AAAA 记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM