[英]How to call a REST end point using Airflow DAG
我是 Apache Airflow 的新手。 我想使用 DAG 调用 REST 端点。 例如 REST 端点
@PostMapping(path = "/api/employees", consumes = "application/json")
现在我想使用 Airflow DAG 调用这个休息端点,并安排它。 我正在做的是使用 SimpleHttpOperator 来调用 Rest 端点。
t1 = SimpleHttpOperator(
task_id='post_op',
endpoint='http://localhost:8084/api/employees',
data=json.dumps({"department": "Digital","id": 102,"name": "Rakesh","salary": 80000}),
headers={"Content-Type": "application/json"},
dag=dag,)
当我触发 DAG 时,任务失败
[2019-12-30 09:09:06,330] {{taskinstance.py:862}} INFO - Executing <Task(SimpleHttpOperator):
post_op> on 2019-12-30T08:57:00.674386+00:00
[2019-12-30 09:09:06,331] {{base_task_runner.py:133}} INFO - Running: ['airflow', 'run',
'example_http_operator', 'post_op', '2019-12-30T08:57:00.674386+00:00', '--job_id', '6', '--pool',
'default_pool', '--raw', '-sd', 'DAGS_FOLDER/ExampleHttpOperator.py', '--cfg_path',
'/tmp/tmpf9t6kzxb']
[2019-12-30 09:09:07,446] {{base_task_runner.py:115}} INFO - Job 6: Subtask post_op [2019-12-30
09:09:07,445] {{__init__.py:51}} INFO - Using executor SequentialExecutor
[2019-12-30 09:09:07,446] {{base_task_runner.py:115}} INFO - Job 6: Subtask post_op [2019-12-30
09:09:07,446] {{dagbag.py:92}} INFO - Filling up the DagBag from
/usr/local/airflow/dags/ExampleHttpOperator.py
[2019-12-30 09:09:07,473] {{base_task_runner.py:115}} INFO - Job 6: Subtask post_op [2019-12-30
09:09:07,472] {{cli.py:545}} INFO - Running <TaskInstance: example_http_operator.post_op 2019-12-
30T08:57:00.674386+00:00 [running]> on host 855dbc2ce3a3
[2019-12-30 09:09:07,480] {{http_operator.py:87}} INFO - Calling HTTP method
[2019-12-30 09:09:07,483] {{logging_mixin.py:112}} INFO - [2019-12-30 09:09:07,483]
{{base_hook.py:84}} INFO - Using connection to: id: http_default. Host: https://www.google.com/,
Port: None, Schema: None, Login: None, Password: None, extra: {}
[2019-12-30 09:09:07,484] {{logging_mixin.py:112}} INFO - [2019-12-30 09:09:07,484]
{{http_hook.py:131}} INFO - Sending 'POST' to url:
https://www.google.com/http://localhost:8084/api/employees
[2019-12-30 09:09:07,501] {{logging_mixin.py:112}} INFO - [2019-12-30 09:09:07,501]
{{http_hook.py:181}} WARNING - HTTPSConnectionPool(host='www.google.com', port=443): Max retries
exceeded with url: /http://localhost:8084/api/employees (Caused by SSLError(SSLError("bad handshake:
SysCallError(-1, 'Unexpected EOF')"))) Tenacity will retry to execute the operation
[2019-12-30 09:09:07,501] {{taskinstance.py:1058}} ERROR -
HTTPSConnectionPool(host='www.google.com', port=443): Max retries exceeded with url:
/http://localhost:8084/api/employees (Caused by SSLError(SSLError("bad handshake: SysCallError(-1,
'Unexpected EOF')")))
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/urllib3/contrib/pyopenssl.py", line 485, in wrap_socket
cnx.do_handshake()
File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1934, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "/usr/local/lib/python3.7/site-packages/OpenSSL/SSL.py", line 1664, in _raise_ssl_error
raise SysCallError(-1, "Unexpected EOF")
OpenSSL.SSL.SysCallError: (-1, 'Unexpected EOF')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 672, in urlopen
chunked=chunked,
File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 376, in _make_request
self._validate_conn(conn)
File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 994, in _validate_conn
conn.connect()
File "/usr/local/lib/python3.7/site-packages/urllib3/connection.py", line 394, in connect
ssl_context=context,
File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 370, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/local/lib/python3.7/site-packages/urllib3/contrib/pyopenssl.py", line 491, in wrap_socket
raise ssl.SSLError("bad handshake: %r" % e)
ssl.SSLError: ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
Airflow 在 Docker 上运行,docker 镜像是puckel/docker-airflow 。 为什么它调用主机http_default。 主持人: https ://www.google.com/
您需要考虑您正在使用的Operator
以及它用于连接的底层Hook
。 Hook
从 Airflow Connection 获取连接信息, Airflow Connection
只是一个用于存储凭据和其他连接信息的容器。 您可以在 Airflow UI 中配置Connections
(使用 Airflow UI -> Admin -> Connections)。
所以在这种情况下,您需要首先配置您的 HTTP Connection
。
http_conn_id (str) – connection that has the base API url i.e https://www.google.com/
碰巧的是,对于httpHook
,您应该通过将host
参数设置为等于端点的base_url
来配置Connection
: http://localhost:8084/
。
由于您的运营商具有默认的http_conn_id
,因此该挂钩将使用 Airflow UI 中名为“http_default”的Airflow Connection
。 如果您不想更改默认连接,您可以使用 Airflow UI 创建另一个Airflow Connection
,并将新的 conn_id 参数传递给您的操作员。
请参阅源代码以更好地了解如何使用Connection
对象。
最后,根据http_operator 文档:
endpoint (str) – The relative part of the full url. (templated)
您应该只将 URL 的相对部分传递给操作员。 其余部分将从底层http_hook
获得。
在这种情况下,您的Operator
的endpoint
值应该是api/employees
(而不是完整的 URL)。
不幸的是,Airflow 项目文档在这种情况下不是很清楚。 请考虑做出改进,他们总是受欢迎的:)
我认为您需要在 Dockerfile 或 docker run 命令中设置连接字符串的 ENV 变量:
ENV AIRFLOW__CORE__SQL_ALCHEMY_CONN my_conn_string
连接
与外部系统的连接信息存储在 Airflow 元数据数据库中,并在 UI 中进行管理(菜单 -> 管理 -> 连接)在那里定义了一个 conn_id,并附加了主机名/登录名/密码/架构信息。 气流管道可以简单地引用集中管理的 conn_id,而无需在任何地方硬编码任何此类信息。
可以定义许多具有相同 conn_id 的连接,在这种情况下,当钩子使用 BaseHook 中的 get_connection 方法时,Airflow 将随机选择一个连接,在与重试结合使用时允许一些基本的负载平衡和容错。
Airflow 还能够通过操作系统中的环境变量引用连接。 环境变量需要以 AIRFLOW_CONN_ 为前缀才能被视为连接。 在 Airflow 管道中引用连接时,conn_id 应该是不带前缀的变量名称。 例如,如果 conn_id 命名为 POSTGRES_MASTER,则环境变量应命名为 AIRFLOW_CONN_POSTGRES_MASTER。 Airflow 假定从环境变量返回的值采用 URI 格式(例如 postgres://user:password@localhost:5432/master)。
看到这个
因此您现在使用默认值:
Using connection to: id: http_default. Host: https://www.google.com/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.