2016-09-30 2 views
0

파이썬 요청 라이브러리가 SRV 레코드를 사용하여 영사 도메인 이름을 해석하고 요청할 때 올바른 IP 주소와 포트를 사용할 수 있습니까?SRV DNS 레코드를 파이썬 요청 라이브러리와 함께 사용

예를 들어, serviceA가 포트 8080의 IP 주소 172.18.0.5로 실행 중이며이 서비스가 영사에 등록되어있는 경우를 가정합니다. 그리고 호스트에 대한 DNS가 consul을 사용하여 쿼리를 해결하도록 설정되어 있다고 가정합니다. 내가 좋아하는 요청을 만들 수 :

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

을하고 요청에 해당 할 수 있습니다

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

답변

0

this answer을 사용하여 요청을 처리하는 패치를 작성했습니다. 요청 라이브러리에 대한 업데이트로 인해 일부 변경해야했습니다. 이 패치는 2.11.1 버전의 요청과 함께 작동합니다.

dnspython 라이브러리를 사용하여 SRV 레코드를 해결했으며 consul이 환경 변수 CONSUL_DNS_IP_PORT로 사용할 수있는 DNS 요청을 수신하는 IP 주소와 포트를 예상합니다. 패치를 사용하려면 패치가있는 모듈에서 requests_use_srv_records 함수를 가져온 다음 호출하십시오. .service.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 
: 여기

패치입니다
0

아니, 당신은 당신이 requests를 다시 작성하지 않는 한.

SRV 레코드는 서비스를 찾기위한 디자인입니다.
이 경우 이미 http를 사용하고 있음을 나타냅니다. 따라서 고객은 serviceA.service.consul에 대해서만 A 또는 AAAA 레코드를 쿼리합니다.

관련 문제