You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Airflow DAG内调用REST API失败的原因排查

问题描述

我在Docker中运行本地Airflow实例(v2.6.1版本),在Airflow外部的本地文件中调用Airflow REST API创建连接可正常执行:

import requests

def create_connection():
    response = requests.post(
        url='http://localhost:8080/api/v1/connections',
        headers={
            'Content-type': 'application/json',
            'Accept': 'application/json'
        },
        auth=(
            'my_airflow_username',
            'my_airflow_password'
        ),
        json={
            'connection_id': 'new_connection',
            'conn_type': 'generic',
            'description': 'this is the description'
        }
    )
    return response

print(create_connection().status_code)

返回状态码200并按预期创建连接。但将相同代码放入DAG中执行时:

from datetime import datetime
from airflow.decorators import dag
from airflow.operators.python import PythonOperator
import requests

@dag(
    dag_id=f'test_dag',
    start_date=datetime(2023,5,11),
    schedule_interval=None,
    max_active_runs=1
)

def execute():

    def create_connection():
        response = requests.post(
            url='http://localhost:8080/api/v1/connections',
            headers={
                'Content-type': 'application/json',
                'Accept': 'application/json'
            },
            auth=(
                'my_airflow_username',
                'my_airflow_password'
            ),
            json={
                'connection_id': 'new_connection',
                'conn_type': 'generic',
                'description': 'this is the description'
            }
        )
        return response

    create_connection = PythonOperator(
        task_id='create_connection',
        python_callable=create_connection
    )

    create_connection
    
execute()

出现错误并返回如下栈追踪:

Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connection.py", line 175, in _new_conn
    (self._dns_host, self.port), self.timeout, **extra_kw
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/util/connection.py", line 95, in create_connection
    raise err
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/util/connection.py", line 85, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 710, in urlopen
    chunked=chunked,
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 398, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connection.py", line 244, in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
  File "/usr/local/lib/python3.7/http/client.py", line 1281, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/lib/python3.7/http/client.py", line 1327, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.7/http/client.py", line 1276, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/lib/python3.7/http/client.py", line 1036, in _send_output
    self.send(msg)
  File "/usr/local/lib/python3.7/http/client.py", line 976, in send
    self.connect()
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connection.py", line 205, in connect
    conn = self._new_conn()
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connection.py", line 187, in _new_conn
    self, "Failed to establish a new connection: %s" % e
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0xffff8bb14090>: Failed to establish a new connection: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.7/site-packages/requests/adapters.py", line 497, in send
    chunked=chunked,
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 788, in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
  File "/home/airflow/.local/lib/python3.7/site-packages/urllib3/util/retry.py", line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /api/v1/connections (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0xffff8bb14090>: Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.7/site-packages/airflow/operators/python.py", line 181, in execute
    return_value = self.execute_callable()
  File "/home/airflow/.local/lib/python3.7/site-packages/airflow/operators/python.py", line 198, in execute_callable
    return self.python_callable(*self.op_args, **self.op_kwargs)
  File "/opt/airflow/dags/crmf/development/credential_testing/dag2.py", line 31, in create_connection
    'description': 'this is the description'
  File "/home/airflow/.local/lib/python3.7/site-packages/requests/api.py", line 115, in post
    return request("post", url, data=data, json=json, **kwargs)
  File "/home/airflow/.local/lib/python3.7/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/airflow/.local/lib/python3.7/site-packages/requests/sessions.py", line 587, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/airflow/.local/lib/python3.7/site-packages/requests/sessions.py", line 701, in send
    r = adapter.send(request, **kwargs)
  File "/home/airflow/.local/lib/python3.7/site-packages/requests/adapters.py", line 519, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /api/v1/connections (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0xffff8bb14090>: Failed to establish a new connection: [Errno 111] Connection refused'))

我期望能像调用其他API一样在DAG内调用Airflow API,请问为何Airflow API连接失败?


原因及解决方法

核心原因

Docker容器内的localhost指向容器自身,而非宿主机。本地外部调用http://localhost:8080时,请求指向宿主机暴露的Airflow Webserver端口;但DAG任务运行在Airflow Worker(或Scheduler)容器中,此时localhost指代Worker容器本身,而Worker容器并未在8080端口启动Webserver服务,因此出现连接拒绝错误。

解决方法

方法1:使用Webserver容器名称作为主机名

Docker Compose部署的Airflow中,Webserver容器默认名称为airflow-webserver。将API请求URL修改为:

url='http://airflow-webserver:8080/api/v1/connections'

容器名称可在docker-compose.yaml中确认,确保Worker与Webserver容器处于同一Docker网络(Compose默认会创建统一网络)。

方法2:替换为宿主机局域网IP

找到宿主机的局域网IP(如192.168.1.100),修改URL:

url='http://192.168.1.100:8080/api/v1/connections'

注意:此方式依赖宿主机IP稳定,IP变动需同步修改。

方法3:直接使用Airflow内部API创建连接(推荐)

无需通过REST API绕路,Airflow提供内部方法直接操作连接,更高效且避免网络问题。修改DAG中的create_connection函数:

from airflow.models.connection import Connection
from airflow.utils.session import create_session

def create_connection():
    conn = Connection(
        conn_id='new_connection',
        conn_type='generic',
        description='this is the description'
    )
    with create_session() as session:
        if not session.query(Connection).filter(Connection.conn_id == conn.conn_id).first():
            session.add(conn)
            session.commit()
            return "Connection created successfully"
        else:
            return "Connection already exists"

该方式直接操作Airflow元数据库,无需网络请求,是更规范的实现方式。


内容的提问来源于stack exchange,提问作者gbeaven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 08:05:00