将SRV DNS记录与python请求库一起使用

埃德鲁

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

例如,假设我在端口8080上运行的IP地址为172.18.0.5的serviceA,并且此服务已在consul中注册。并且考虑到主机的DNS设置为使用领事来解析查询。我可以提出以下要求吗?

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从补丁所在的任何模块导入功能,然后调用它。它只会尝试对以结尾的主机使用consul SRV记录.service.consul,其他主机将得到定期解决。

这是补丁:

# 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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章